Skip to content

Commit

Permalink
Merge branch 'master' into migrate-table-to-rtl
Browse files Browse the repository at this point in the history
  • Loading branch information
illiteratewriter committed Mar 3, 2023
2 parents 0bfcf0e + bff2d81 commit 86c6d4e
Show file tree
Hide file tree
Showing 25 changed files with 160 additions and 110 deletions.
2 changes: 1 addition & 1 deletion src/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Dropdown extends React.Component {
const menu = this.getMenu();
const toggle = this.getToggle();

const targetIsToggle = e.target === toggle;
const targetIsToggle = toggle.contains(e.target);
const clickIsInMenu = menu && menu.contains(e.target) && menu !== e.target;

let clickIsInInput = false;
Expand Down
8 changes: 5 additions & 3 deletions src/Fade.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Transition } from 'react-transition-group';
Expand Down Expand Up @@ -42,22 +42,24 @@ const defaultProps = {
};

function Fade(props) {
const ref = useRef(null);

const {
tag: Tag,
baseClass,
baseClassActive,
className,
cssModule,
children,
innerRef,
innerRef = ref,
...otherProps
} = props;

const transitionProps = pick(otherProps, TransitionPropTypeKeys);
const childProps = omit(otherProps, TransitionPropTypeKeys);

return (
<Transition {...transitionProps}>
<Transition nodeRef={innerRef} {...transitionProps}>
{(status) => {
const isActive = status === 'entered';
const classes = mapToCssModules(
Expand Down
4 changes: 2 additions & 2 deletions src/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ class Modal extends React.Component {
if (Modal.openCount < 1) {
Modal.originalBodyOverflow = window.getComputedStyle(
document.body,
).overflow;
};
).overflow;
}
conditionallyUpdateScrollbar();

if (Modal.openCount === 0) {
Expand Down
1 change: 0 additions & 1 deletion src/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const propTypes = {
expand: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
/** Make the navbar fixed at the top */
fixed: PropTypes.string,
full: PropTypes.bool,
/** Add `.navbar-light` class */
light: PropTypes.bool,
role: PropTypes.string,
Expand Down
3 changes: 3 additions & 0 deletions src/Offcanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,9 @@ class Offcanvas extends React.Component {
classNames('offcanvas-backdrop', 'show', backdropClassName),
cssModule,
)}
ref={(c) => {
this._backdrop = c;
}}
onClick={this.handleBackdropClick}
onMouseDown={this.handleBackdropMouseDown}
/>
Expand Down
50 changes: 16 additions & 34 deletions src/__tests__/Alert.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Alert } from '..';
describe('Alert', () => {
beforeEach(() => {
jest.resetModules();
jest.useFakeTimers();
});

it('should render children', () => {
Expand Down Expand Up @@ -104,36 +105,15 @@ describe('Alert', () => {
});

it('should have default transitionTimeouts', () => {
jest.doMock('react-transition-group', () => ({
Transition: jest.fn(() => null),
}));
// eslint-disable-next-line global-require
const { Transition } = require('react-transition-group');
// eslint-disable-next-line global-require
const { Alert } = require('..');
render(<Alert>Hello</Alert>);

render(<Alert>Yo!</Alert>);
expect(screen.getByText(/hello/i)).not.toHaveClass('show');

expect(Transition).toHaveBeenCalledWith(
expect.objectContaining({
timeout: 150,
appear: true,
enter: true,
exit: true,
}),
{},
);
jest.advanceTimersByTime(150);
expect(screen.getByText(/hello/i)).toHaveClass('show');
});

it('should have support configurable transitionTimeouts', () => {
jest.doMock('react-transition-group', () => ({
Transition: jest.fn(() => null),
}));
// eslint-disable-next-line global-require
const { Transition } = require('react-transition-group');
// eslint-disable-next-line global-require
const { Alert } = require('..');

render(
<Alert
transition={{
Expand All @@ -143,18 +123,20 @@ describe('Alert', () => {
exit: false,
}}
>
Yo!
Hello
</Alert>,
);

expect(Transition).toHaveBeenCalledWith(
expect.objectContaining({
timeout: 0,
appear: false,
enter: false,
exit: false,
}),
{},
expect(screen.getByText(/hello/i)).toHaveClass('show');
});

it('works with strict mode', () => {
const spy = jest.spyOn(console, 'error');
render(
<React.StrictMode>
<Alert>Hello</Alert>
</React.StrictMode>,
);
expect(spy).not.toHaveBeenCalled();
});
});
51 changes: 51 additions & 0 deletions src/__tests__/Dropdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,38 @@ describe('Dropdown', () => {
expect(toggle).not.toHaveBeenCalled();
});

it('should call toggle when DropdownToggle is clicked ', () => {
const toggle = jest.fn();
render(
<Dropdown isOpen toggle={toggle}>
<DropdownToggle>Toggle</DropdownToggle>
<DropdownMenu>
<DropdownItem>Test</DropdownItem>
</DropdownMenu>
</Dropdown>,
);

user.click(screen.getByText(/toggle/i));
expect(toggle).toHaveBeenCalledTimes(1);
});

it('should call toggle when DropdownToggle with non string children is clicked ', () => {
const toggle = jest.fn();
render(
<Dropdown isOpen toggle={toggle}>
<DropdownToggle>
<div>Toggle</div>
</DropdownToggle>
<DropdownMenu>
<DropdownItem>Test</DropdownItem>
</DropdownMenu>
</Dropdown>,
);

user.click(screen.getByText(/toggle/i));
expect(toggle).toHaveBeenCalledTimes(1);
});

describe('handleProps', () => {
it('should not pass custom props to html attrs', () => {
const toggle = jest.fn();
Expand Down Expand Up @@ -213,6 +245,25 @@ describe('Dropdown', () => {
expect(toggle).toHaveBeenCalled();
});

it('should call toggle on container click', () => {
const toggle = jest.fn();

render(
<Dropdown isOpen toggle={toggle} data-testid="dropdown">
<DropdownToggle>
<div>Toggle</div>
</DropdownToggle>
<DropdownMenu>
<DropdownItem>Test</DropdownItem>
</DropdownMenu>
</Dropdown>,
);

user.click(screen.getByTestId('dropdown'));

expect(toggle).toHaveBeenCalled();
});

it('should not call toggle on inner container click', () => {
const toggle = jest.fn();
render(
Expand Down
10 changes: 10 additions & 0 deletions src/__tests__/Modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1105,4 +1105,14 @@ describe('Modal', () => {
user.tab();
expect(screen.getByText(/click 1/i)).toHaveFocus();
});

it('works with strict mode', () => {
const spy = jest.spyOn(console, 'error');
render(
<React.StrictMode>
<Modal isOpen>Hello</Modal>
</React.StrictMode>,
);
expect(spy).not.toHaveBeenCalled();
});
});
23 changes: 8 additions & 15 deletions src/__tests__/ModalBody.spec.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import { ModalBody } from '..';
import {
testForCustomClass,
testForCustomTag,
testForDefaultClass,
} from '../testUtils';

describe('ModalBody', () => {
it('should render with "modal-body" class', () => {
const wrapper = shallow(<ModalBody>Yo!</ModalBody>);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.hasClass('modal-body')).toBe(true);
testForDefaultClass(ModalBody, 'modal-body');
});

it('should render additional classes', () => {
const wrapper = shallow(<ModalBody className="other">Yo!</ModalBody>);

expect(wrapper.hasClass('other')).toBe(true);
expect(wrapper.hasClass('modal-body')).toBe(true);
testForCustomClass(ModalBody, {});
});

it('should render custom tag', () => {
const wrapper = shallow(<ModalBody tag="main">Yo!</ModalBody>);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.hasClass('modal-body')).toBe(true);
expect(wrapper.type()).toBe('main');
testForCustomTag(ModalBody);
});
});
23 changes: 8 additions & 15 deletions src/__tests__/ModalFooter.spec.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import { ModalFooter } from '..';
import {
testForCustomClass,
testForCustomTag,
testForDefaultClass,
} from '../testUtils';

describe('ModalFooter', () => {
it('should render with "modal-footer" class', () => {
const wrapper = shallow(<ModalFooter>Yo!</ModalFooter>);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.hasClass('modal-footer')).toBe(true);
testForDefaultClass(ModalFooter, 'modal-footer');
});

it('should render additional classes', () => {
const wrapper = shallow(<ModalFooter className="other">Yo!</ModalFooter>);

expect(wrapper.hasClass('modal-footer')).toBe(true);
expect(wrapper.hasClass('other')).toBe(true);
testForCustomClass(ModalFooter);
});

it('should render custom tag', () => {
const wrapper = shallow(<ModalFooter tag="main">Yo!</ModalFooter>);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.hasClass('modal-footer')).toBe(true);
expect(wrapper.type()).toBe('main');
testForCustomTag(ModalFooter);
});
});
36 changes: 14 additions & 22 deletions src/__tests__/ModalHeader.spec.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,36 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { ModalHeader } from '..';
import { testForCustomClass, testForDefaultClass } from '../testUtils';

describe('ModalHeader', () => {
it('should render with "modal-header" class', () => {
const wrapper = shallow(<ModalHeader>Yo!</ModalHeader>);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.hasClass('modal-header')).toBe(true);
testForDefaultClass(ModalHeader, 'modal-header');
});

it('should render additional classes', () => {
const wrapper = shallow(<ModalHeader className="other">Yo!</ModalHeader>);

expect(wrapper.hasClass('other')).toBe(true);
expect(wrapper.hasClass('modal-header')).toBe(true);
testForCustomClass(ModalHeader);
});

it('should render close button', () => {
const wrapper = shallow(
<ModalHeader toggle={() => {}} className="other">
render(
<ModalHeader toggle={() => {}} data-testid="test" className="other">
Yo!
</ModalHeader>,
);

expect(wrapper.hasClass('other')).toBe(true);
expect(wrapper.hasClass('modal-header')).toBe(true);
expect(wrapper.find('button.btn-close').length).toBe(1);
const node = screen.getByTestId('test').querySelector('button');
expect(node.tagName.toLowerCase()).toBe('button');
expect(node).toHaveClass('btn-close');
});

it('should render custom tag', () => {
const wrapper = shallow(<ModalHeader tag="p">Yo!</ModalHeader>).childAt(0);

expect(wrapper.text()).toBe('Yo!');
expect(wrapper.type()).toBe('p');
render(<ModalHeader tag="main">hello</ModalHeader>);
expect(screen.getByText(/hello/i).tagName.toLowerCase()).toBe('main');
});

it('should render custom wrapping tag', () => {
const wrapper = shallow(<ModalHeader wrapTag="main">Yo!</ModalHeader>);

expect(wrapper.type()).toBe('main');
render(<ModalHeader data-testid="test" wrapTag="main" />);
expect(screen.getByTestId('test').tagName.toLowerCase()).toMatch('main');
});
});
17 changes: 17 additions & 0 deletions src/__tests__/Offcanvas.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,23 @@ describe('Offcanvas', () => {
expect(toggle).toHaveBeenCalled();
});

it('should call toggle when clicking backdrop when fade is false', () => {
const toggle = jest.fn();
render(
<Offcanvas isOpen toggle={toggle} fade={false}>
<button id="clicker">Does Nothing</button>
</Offcanvas>,
);

user.click(screen.getByText(/does nothing/i));

expect(toggle).not.toHaveBeenCalled();

user.click(document.getElementsByClassName('offcanvas-backdrop')[0]);

expect(toggle).toHaveBeenCalled();
});

it('should destroy this._element', () => {
const { rerender } = render(
<Offcanvas isOpen toggle={toggle}>
Expand Down
6 changes: 5 additions & 1 deletion stories/examples/Dropdown/DirectionKitchen.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export default function Example(args) {
return (
<div className="d-flex p-5 justify-content-center">
{directions.map((direction) => (
<UncontrolledDropdown direction={direction} className="me-2">
<UncontrolledDropdown
direction={direction}
key={direction}
className="me-2"
>
<DropdownToggle caret color="primary">
{`Drop${direction}`}
</DropdownToggle>
Expand Down
Loading

0 comments on commit 86c6d4e

Please sign in to comment.