Anonymous
React Onclick Event не запускается в тестовом примере для кнопки
Сообщение
Anonymous » 06 июн 2025, 00:08
Это мой компонент. Я пытаюсь написать тестовый пример для этого компонента. Метод Togglemenu, который я использовал для события кнопки OnClick, не запускает событие OnClick, когда я пишу тестовые примеры. Я попытался отладить это, но это не запускает событие OnClick.
Код: Выделить всё
import { arrayOf, bool, object, string } from 'prop-types';
import { bindActionCreators } from 'redux';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'classnames';
import { isEqual, throttle } from 'lodash';
import { Button, Icon, Spinner, Text } from 'bsd-react-ui-kit';
import { Search, TooltipButton } from 'bve-react-ui-kit';
import search from '@bsd/ui-utils/search';
import { sort, sortTypes } from '@bsd/ui-utils/sort';
import { clickTracking } from '@bsd/ui-utils/tracking';
import { matchesMin, screen } from '@bsd/ui-utils/window';
import { actions as appActions } from 'modules/application';
import { actions as commonActions } from 'modules/application/common';
import { actions as siteActions } from 'modules/account/sites';
import applicationSelectors from 'modules/application/selectors';
import siteSelectors from 'modules/account/sites/selectors';
import * as commonConstants from 'modules/application/common/constants';
import * as constants from 'modules/account/sites/constants';
import {
convertStringToNumber,
getPathname,
searchAnalyticsOnBlur,
searchAnalyticsOnFocus,
truncateWord
} from 'modules/utilities';
const SiteSwitcher = ({
availableSites,
content,
dashboard,
defaultSiteId,
path
}) => {
const baseClass = 'bve-site-switcher';
const locationClass = dashboard ? '' : `${baseClass}-no-dashboard`;
const siteList = useRef();
const dispatch = useDispatch();
const actions = bindActionCreators(
{
...appActions,
...commonActions,
...siteActions
},
dispatch
);
const searchShowCount = useSelector(applicationSelectors.getSearchShowCount);
const searchTerm = useSelector(siteSelectors.getSitesSearchTerm);
const selectedSiteId = useSelector(siteSelectors.getSelectedSiteId);
const spinnerStatus = useSelector(siteSelectors.getDefaultLoaded);
const [data, setData] = useState(availableSites);
const [isDesktop, setIsDesktop] = useState(matchesMin(screen.medium));
const [isTablet, setIsTablet] = useState(matchesMin(screen.small));
const [expanded, setExpanded] = useState(false);
const [spinner, setSpinner] = useState(
availableSites.map(site => ({
id: site.siteId,
show: false
}))
);
const activeSite = availableSites.find(
site => site.siteId === selectedSiteId
);
const disabled = availableSites.length {
setIsDesktop(matchesMin(screen.medium));
setIsTablet(matchesMin(screen.small));
}, 100),
[]
);
const handleClickOutside = ({ target }) => {
const { className, tagName } = target;
const node = siteList?.current;
const ignoredElements = ['svg', 'use'];
if (!node) {
// Exit early if node is unavailable
return false;
}
const ignore =
ignoredElements.includes(tagName) ||
constants.SITE_SWITCHER.EXCLUSIONS.some(name => className.includes(name));
if (ignore) {
// Exit if target is inside clear search button
return false;
}
if (node && !node.contains(target)) {
// Collapse if target is outside menu and not SVG icon
actions.setShowOverlay(false);
setExpanded(false);
}
};
const opened = useRef(false);
const handleDocumentClick = useCallback(
event => {
if (opened.current) {
opened.current = false;
}
handleClickOutside(event);
},
[handleClickOutside]
);
useEffect(() => {
if (!expanded) {
return;
}
document.addEventListener('click', handleDocumentClick);
return () => {
document.removeEventListener('click', handleDocumentClick);
};
}, [expanded]);
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
actions.setShowOverlay(false);
window.removeEventListener('resize', handleResize);
};
}, []);
const prevSpinnerStatus = useRef(spinnerStatus);
useEffect(() => {
if (!isEqual(prevSpinnerStatus.current, spinnerStatus)) {
const { id, status } = spinnerStatus;
if (status === commonConstants.IN_PROGRESS) {
setSpinner(
spinner.map(item =>
item.id === id ? { ...item, show: true } : { ...item, show: false }
)
);
} else {
setSpinner(
spinner.map(spin => ({
...spin,
show: false
}))
);
}
prevSpinnerStatus.current = spinnerStatus;
}
}, [expanded, spinnerStatus]);
const toggleMenu = event => {
// event.preventDefault();
console.log('Toggle menu called');
if (!expanded && event?.currentTarget === document) {
return false;
}
if (!disabled) {
opened.current = true;
const nextExpanded = !expanded;
actions.setShowOverlay(nextExpanded);
actions.setSitesSearch('');
setExpanded(nextExpanded);
setData([
...availableSites.filter(site => site.siteId === defaultSiteId),
...sort(
availableSites.filter(site => site.siteId !== defaultSiteId),
sortTypes.ALPHABETICAL,
constants.SITE_SWITCHER.OPTION_KEY
)
]);
}
};
const secondaryLabel = () => {
if (!dashboard) {
return null;
}
const address = activeSite?.[constants.SITE_SWITCHER.SUBLABEL_KEY];
return truncateWord(address, 40);
};
const optionsLabel = () => {
const labelClass = `${baseClass}-dropdown-label`;
const optionCount = ` (${data.length})`;
return (
{`${content.optionsLabel}${optionCount}`}
);
};
const handleSearch = term => {
if (term.length) {
actions.setSitesSearch(term);
} else {
actions.setSitesSearch('');
}
};
const searchLabel = () => {
const searchLabelClass = `${baseClass}-dropdown-search-label`;
return (
{content.siteSearchLabel}
);
};
const searchBar = () => {
const count = searchShowCount
? convertStringToNumber(searchShowCount)
: constants.SITE_SWITCHER.SHOW_SEARCH;
if (availableSites?.length searchAnalyticsOnFocus(actions)}
onSearch={handleSearch}
placeholder={content.siteSearchPlaceholder}
/>
);
};
const renderOption = option => {
const { siteAddress, siteName } = option;
return (
{truncateWord(siteName, 35)}
{truncateWord(siteAddress, 40)}
);
};
const handleOptionClick = (event, buttonValue) => {
if (buttonValue.siteId !== selectedSiteId) {
actions.setSitesSearch('');
actions.switchSite({
groupId: buttonValue?.services[0].groupId,
path,
siteId: buttonValue.siteId
});
}
toggleMenu(event);
};
const getFilteredData = () => {
let result;
if (searchTerm) {
result = search(searchTerm, data, constants.SITE_SWITCHER.SEARCH_KEYS);
} else {
result = data;
}
return Array.isArray(result) ? result : [];
};
const noSearchResults = () => {
return (
{content.searchEmptyHeading}
);
};
const defaultBadge = () => {
const { defaultBadgeText, tooltipText } = content;
const top = !isDesktop && !isTablet ? 30 : 60;
const left = !isDesktop && !isTablet ? 60 : -150;
return (
{tooltipText}
);
};
const handleDefaultClick = selectedDefault => {
const { siteId } = selectedDefault;
actions.updateDefaultSite(siteId);
};
const renderMakeDefaultLink = option => {
if (defaultSiteId === option.siteId) {
return defaultBadge();
}
return (
handleDefaultClick(option)}
size="s"
>
{content.defaultLinkText}
);
};
const defaultOption = () => {
const defaultClass = `${baseClass}-option-default`;
const containerClass = `${baseClass}-option-container`;
const newDefault = data.find(site => site.siteId === defaultSiteId);
return (
[*]
handleOptionClick(event, newDefault)}
>
{renderOption(newDefault)}
{renderMakeDefaultLink(newDefault)}
);
};
const dropdownOptions = () => {
if (searchTerm && !getFilteredData().length) {
return [*]{noSearchResults()};
}
return getFilteredData().map((option, index) => {
if (option.siteId === defaultSiteId) {
return defaultOption();
}
const optionClass = `${baseClass}-option`;
const textOption = renderOption(option);
const containerClass = `${optionClass}-container`;
const showSpinner = spinner.find(
spinnerItem => spinnerItem.id === option.siteId
).show;
const { SITE_SELECTION_CLICK } = commonConstants.default.tracking;
return (
[*]
handleOptionClick(event, option)}
>
{textOption}
{!showSpinner && renderMakeDefaultLink(option)}
);
});
};
const customDropdown = () => {
console.log('Custom dropdown called');
console.log('availableSites.length:', availableSites.length);
const siteLabel = activeSite?.[constants.SITE_SWITCHER.OPTION_KEY];
const isMyProfileRoute = getPathname().includes('my-profile');
console.log('checking isMyProfileRoute:', isMyProfileRoute);
console.log('disabled', disabled);
let selectClass = classNames({
[`${baseClass}-select`]: !disabled,
[`${baseClass}-select--disabled`]: disabled
});
if (isMyProfileRoute) {
selectClass = `${baseClass}-select--disabled`;
}
const dropdownClass = `${baseClass}-dropdown`;
const labelClass = classNames({
[`${selectClass}-label`]: !expanded,
[`${selectClass}-label--expanded`]: expanded
});
const icon = 'marker-outline';
const { SITE_SWITCHER_CLICK } = commonConstants.default.tracking;
return (
toggleMenu(event)}
>
{truncateWord(siteLabel, 35)}
{secondaryLabel()}
{expanded && (
{optionsLabel()}
{searchBar()}
[list]
{dropdownOptions()}
[/list]
)}
);
};
return (
{customDropdown()}
);
};
SiteSwitcher.propTypes = {
availableSites: arrayOf(object),
content: object,
dashboard: bool,
defaultSiteId: string,
path: string
};
SiteSwitcher.defaultProps = {
dashboard: false
};
export default SiteSwitcher;
< /code>
Тестовый пример:
it.only('renders и показывает выпадающую сторону, когда переключатель сайта нажимается ', async () => {
render (
); screen.getbytestid ('site-address'); < /p>
fireEvent.click(button);
screen.debug();
expect(button).toBeInTheDocument();
await waitFor(() => {
// expect(
// container.querySelector('.bve-site-switcher-dropdown')
// ).toBeInTheDocument();
expect(screen.getByText('Philadelphia')).toBeInTheDocument();
expect(screen.getByText('Chicago')).toBeInTheDocument();
});
// waitFor(() => {
// fireEvent.click(button);
// expect(
// document.querySelector('.bve-site-switcher-dropdown')
// ).toBeInTheDocument();
// });
// failing test case logic
// fireEvent.click(button);
// waitFor(() => {
// expect(document.querySelector('.bve-site-switcher-dropdown')).toBeInTheDocument();
// });
});
Подробнее здесь:
https://stackoverflow.com/questions/796 ... for-button
1749157726
Anonymous
Это мой компонент. Я пытаюсь написать тестовый пример для этого компонента. Метод Togglemenu, который я использовал для события кнопки OnClick, не запускает событие OnClick, когда я пишу тестовые примеры. Я попытался отладить это, но это не запускает событие OnClick.[code]import { arrayOf, bool, object, string } from 'prop-types'; import { bindActionCreators } from 'redux'; import { useDispatch, useSelector } from 'react-redux'; import classNames from 'classnames'; import { isEqual, throttle } from 'lodash'; import { Button, Icon, Spinner, Text } from 'bsd-react-ui-kit'; import { Search, TooltipButton } from 'bve-react-ui-kit'; import search from '@bsd/ui-utils/search'; import { sort, sortTypes } from '@bsd/ui-utils/sort'; import { clickTracking } from '@bsd/ui-utils/tracking'; import { matchesMin, screen } from '@bsd/ui-utils/window'; import { actions as appActions } from 'modules/application'; import { actions as commonActions } from 'modules/application/common'; import { actions as siteActions } from 'modules/account/sites'; import applicationSelectors from 'modules/application/selectors'; import siteSelectors from 'modules/account/sites/selectors'; import * as commonConstants from 'modules/application/common/constants'; import * as constants from 'modules/account/sites/constants'; import { convertStringToNumber, getPathname, searchAnalyticsOnBlur, searchAnalyticsOnFocus, truncateWord } from 'modules/utilities'; const SiteSwitcher = ({ availableSites, content, dashboard, defaultSiteId, path }) => { const baseClass = 'bve-site-switcher'; const locationClass = dashboard ? '' : `${baseClass}-no-dashboard`; const siteList = useRef(); const dispatch = useDispatch(); const actions = bindActionCreators( { ...appActions, ...commonActions, ...siteActions }, dispatch ); const searchShowCount = useSelector(applicationSelectors.getSearchShowCount); const searchTerm = useSelector(siteSelectors.getSitesSearchTerm); const selectedSiteId = useSelector(siteSelectors.getSelectedSiteId); const spinnerStatus = useSelector(siteSelectors.getDefaultLoaded); const [data, setData] = useState(availableSites); const [isDesktop, setIsDesktop] = useState(matchesMin(screen.medium)); const [isTablet, setIsTablet] = useState(matchesMin(screen.small)); const [expanded, setExpanded] = useState(false); const [spinner, setSpinner] = useState( availableSites.map(site => ({ id: site.siteId, show: false })) ); const activeSite = availableSites.find( site => site.siteId === selectedSiteId ); const disabled = availableSites.length { setIsDesktop(matchesMin(screen.medium)); setIsTablet(matchesMin(screen.small)); }, 100), [] ); const handleClickOutside = ({ target }) => { const { className, tagName } = target; const node = siteList?.current; const ignoredElements = ['svg', 'use']; if (!node) { // Exit early if node is unavailable return false; } const ignore = ignoredElements.includes(tagName) || constants.SITE_SWITCHER.EXCLUSIONS.some(name => className.includes(name)); if (ignore) { // Exit if target is inside clear search button return false; } if (node && !node.contains(target)) { // Collapse if target is outside menu and not SVG icon actions.setShowOverlay(false); setExpanded(false); } }; const opened = useRef(false); const handleDocumentClick = useCallback( event => { if (opened.current) { opened.current = false; } handleClickOutside(event); }, [handleClickOutside] ); useEffect(() => { if (!expanded) { return; } document.addEventListener('click', handleDocumentClick); return () => { document.removeEventListener('click', handleDocumentClick); }; }, [expanded]); useEffect(() => { window.addEventListener('resize', handleResize); return () => { actions.setShowOverlay(false); window.removeEventListener('resize', handleResize); }; }, []); const prevSpinnerStatus = useRef(spinnerStatus); useEffect(() => { if (!isEqual(prevSpinnerStatus.current, spinnerStatus)) { const { id, status } = spinnerStatus; if (status === commonConstants.IN_PROGRESS) { setSpinner( spinner.map(item => item.id === id ? { ...item, show: true } : { ...item, show: false } ) ); } else { setSpinner( spinner.map(spin => ({ ...spin, show: false })) ); } prevSpinnerStatus.current = spinnerStatus; } }, [expanded, spinnerStatus]); const toggleMenu = event => { // event.preventDefault(); console.log('Toggle menu called'); if (!expanded && event?.currentTarget === document) { return false; } if (!disabled) { opened.current = true; const nextExpanded = !expanded; actions.setShowOverlay(nextExpanded); actions.setSitesSearch(''); setExpanded(nextExpanded); setData([ ...availableSites.filter(site => site.siteId === defaultSiteId), ...sort( availableSites.filter(site => site.siteId !== defaultSiteId), sortTypes.ALPHABETICAL, constants.SITE_SWITCHER.OPTION_KEY ) ]); } }; const secondaryLabel = () => { if (!dashboard) { return null; } const address = activeSite?.[constants.SITE_SWITCHER.SUBLABEL_KEY]; return truncateWord(address, 40); }; const optionsLabel = () => { const labelClass = `${baseClass}-dropdown-label`; const optionCount = ` (${data.length})`; return ( {`${content.optionsLabel}${optionCount}`} ); }; const handleSearch = term => { if (term.length) { actions.setSitesSearch(term); } else { actions.setSitesSearch(''); } }; const searchLabel = () => { const searchLabelClass = `${baseClass}-dropdown-search-label`; return ( {content.siteSearchLabel} ); }; const searchBar = () => { const count = searchShowCount ? convertStringToNumber(searchShowCount) : constants.SITE_SWITCHER.SHOW_SEARCH; if (availableSites?.length searchAnalyticsOnFocus(actions)} onSearch={handleSearch} placeholder={content.siteSearchPlaceholder} /> ); }; const renderOption = option => { const { siteAddress, siteName } = option; return ( {truncateWord(siteName, 35)} {truncateWord(siteAddress, 40)} ); }; const handleOptionClick = (event, buttonValue) => { if (buttonValue.siteId !== selectedSiteId) { actions.setSitesSearch(''); actions.switchSite({ groupId: buttonValue?.services[0].groupId, path, siteId: buttonValue.siteId }); } toggleMenu(event); }; const getFilteredData = () => { let result; if (searchTerm) { result = search(searchTerm, data, constants.SITE_SWITCHER.SEARCH_KEYS); } else { result = data; } return Array.isArray(result) ? result : []; }; const noSearchResults = () => { return ( {content.searchEmptyHeading} ); }; const defaultBadge = () => { const { defaultBadgeText, tooltipText } = content; const top = !isDesktop && !isTablet ? 30 : 60; const left = !isDesktop && !isTablet ? 60 : -150; return ( {tooltipText} ); }; const handleDefaultClick = selectedDefault => { const { siteId } = selectedDefault; actions.updateDefaultSite(siteId); }; const renderMakeDefaultLink = option => { if (defaultSiteId === option.siteId) { return defaultBadge(); } return ( handleDefaultClick(option)} size="s" > {content.defaultLinkText} ); }; const defaultOption = () => { const defaultClass = `${baseClass}-option-default`; const containerClass = `${baseClass}-option-container`; const newDefault = data.find(site => site.siteId === defaultSiteId); return ( [*] handleOptionClick(event, newDefault)} > {renderOption(newDefault)} {renderMakeDefaultLink(newDefault)} ); }; const dropdownOptions = () => { if (searchTerm && !getFilteredData().length) { return [*]{noSearchResults()}; } return getFilteredData().map((option, index) => { if (option.siteId === defaultSiteId) { return defaultOption(); } const optionClass = `${baseClass}-option`; const textOption = renderOption(option); const containerClass = `${optionClass}-container`; const showSpinner = spinner.find( spinnerItem => spinnerItem.id === option.siteId ).show; const { SITE_SELECTION_CLICK } = commonConstants.default.tracking; return ( [*] handleOptionClick(event, option)} > {textOption} {!showSpinner && renderMakeDefaultLink(option)} ); }); }; const customDropdown = () => { console.log('Custom dropdown called'); console.log('availableSites.length:', availableSites.length); const siteLabel = activeSite?.[constants.SITE_SWITCHER.OPTION_KEY]; const isMyProfileRoute = getPathname().includes('my-profile'); console.log('checking isMyProfileRoute:', isMyProfileRoute); console.log('disabled', disabled); let selectClass = classNames({ [`${baseClass}-select`]: !disabled, [`${baseClass}-select--disabled`]: disabled }); if (isMyProfileRoute) { selectClass = `${baseClass}-select--disabled`; } const dropdownClass = `${baseClass}-dropdown`; const labelClass = classNames({ [`${selectClass}-label`]: !expanded, [`${selectClass}-label--expanded`]: expanded }); const icon = 'marker-outline'; const { SITE_SWITCHER_CLICK } = commonConstants.default.tracking; return ( toggleMenu(event)} > {truncateWord(siteLabel, 35)} {secondaryLabel()} {expanded && ( {optionsLabel()} {searchBar()} [list] {dropdownOptions()} [/list] )} ); }; return ( {customDropdown()} ); }; SiteSwitcher.propTypes = { availableSites: arrayOf(object), content: object, dashboard: bool, defaultSiteId: string, path: string }; SiteSwitcher.defaultProps = { dashboard: false }; export default SiteSwitcher; < /code> Тестовый пример: it.only('renders и показывает выпадающую сторону, когда переключатель сайта нажимается ', async () => { render ( ); screen.getbytestid ('site-address'); < /p> fireEvent.click(button); screen.debug(); expect(button).toBeInTheDocument(); await waitFor(() => { // expect( // container.querySelector('.bve-site-switcher-dropdown') // ).toBeInTheDocument(); expect(screen.getByText('Philadelphia')).toBeInTheDocument(); expect(screen.getByText('Chicago')).toBeInTheDocument(); }); // waitFor(() => { // fireEvent.click(button); // expect( // document.querySelector('.bve-site-switcher-dropdown') // ).toBeInTheDocument(); // }); // failing test case logic // fireEvent.click(button); // waitFor(() => { // expect(document.querySelector('.bve-site-switcher-dropdown')).toBeInTheDocument(); // }); [/code] }); Подробнее здесь: [url]https://stackoverflow.com/questions/79655200/react-onclick-event-is-not-firing-in-test-case-for-button[/url]