planning
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s

This commit is contained in:
2024-10-14 09:15:30 +02:00
parent bcba00a730
commit 6e64e138e2
21059 changed files with 2317811 additions and 1 deletions

View File

@@ -0,0 +1,169 @@
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const shallow = require('enzyme').shallow;
const shallowToJson = require('enzyme-to-json').shallowToJson;
const Button = require('../Button');
const ManagerContext = require('../ManagerContext');
const MockWrapper = require('./helpers/MockWrapper');
const createMockKeyEvent = require('./helpers/createMockKeyEvent');
const createMockManager = require('./helpers/createMockManager');
const createManager = require('../createManager');
const el = React.createElement;
describe('<Button>', function() {
let shallowOptions;
let ambManager;
let downEvent;
let enterEvent;
let spaceEvent;
let escapeEvent;
let fEvent;
beforeEach(function() {
ambManager = createMockManager();
shallowOptions = {
wrappingComponent: ManagerContext.Provider,
wrappingComponentProps: { value: ambManager },
};
downEvent = createMockKeyEvent('ArrowDown');
enterEvent = createMockKeyEvent('Enter');
spaceEvent = createMockKeyEvent(' ');
escapeEvent = createMockKeyEvent('Escape');
fEvent = createMockKeyEvent(null, 70);
});
test('DOM with only required props and text child', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
test('no onBlur prop when closeOnBlur is false', function() {
const manager = createManager({ closeOnBlur: false });
const shallowOptions = {
wrappingComponent: ManagerContext.Provider,
wrappingComponentProps: { value: manager }
};
const wrapper = shallow(el(Button, null, ''), shallowOptions).dive().dive();
expect(shallowToJson(wrapper).props).not.toHaveProperty('onBlur');
});
test('DOM with all possible props and element child', function() {
const button = el(
Button,
{
id: 'foo',
className: 'bar',
style: { top: 2 },
tag: 'button',
disabled: true,
'data-something-something': 'seven' // arbitrary prop
},
el('span', null, 'hooha')
);
const wrapper = shallow(button, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
test('click', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('click');
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
});
test('click when disabled', function() {
const wrapper = shallow(
el(Button, { disabled: true }, 'foo'),
shallowOptions
).dive().dive();
wrapper.simulate('click');
expect(ambManager.toggleMenu).not.toHaveBeenCalled();
});
test('element has disabled attribute when disabled property is set to true', function() {
const wrapper = shallow(
el(Button, { disabled: true, tag: 'button' }, 'foo'),
shallowOptions
).dive().dive();
expect(wrapper.props().disabled).toBeTruthy();
});
test('down arrow when closed', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('keyDown', downEvent);
expect(downEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(ambManager.openMenu).toHaveBeenCalledTimes(1);
expect(ambManager.openMenu).toHaveBeenCalledWith();
});
test('down arrow when open', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
ambManager.isOpen = true;
wrapper.simulate('keyDown', downEvent);
expect(downEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(ambManager.openMenu).not.toHaveBeenCalled();
});
test('enter key', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('keyDown', enterEvent);
expect(enterEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
});
test('space key', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('keyDown', spaceEvent);
expect(spaceEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
});
test('escape key', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('keyDown', escapeEvent);
expect(ambManager.handleMenuKey).toHaveBeenCalledTimes(1);
expect(ambManager.handleMenuKey.mock.calls[0][0].key).toBe('Escape');
});
test('f key', function() {
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
wrapper.simulate('keyDown', fEvent);
expect(ambManager.handleButtonNonArrowKey).toHaveBeenCalledTimes(1);
expect(ambManager.handleButtonNonArrowKey.mock.calls[0][0].keyCode).toBe(
70
);
});
test('enter key when disabled', function() {
const wrapper = shallow(
el(Button, { disabled: true }, 'foo'),
shallowOptions
).dive().dive();
wrapper.simulate('keyDown', enterEvent);
expect(enterEvent.preventDefault).not.toHaveBeenCalled();
expect(ambManager.toggleMenu).not.toHaveBeenCalled();
});
});
describe('<Button> rendered via renderToString', function() {
test('does not throw', function() {
const output = ReactDOMServer.renderToString(
el(
MockWrapper,
{ mockManager: createMockManager() },
el(Button, null, 'foo')
)
);
expect(output).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,130 @@
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const shallow = require('enzyme').shallow;
const mount = require('enzyme').mount;
const shallowToJson = require('enzyme-to-json').shallowToJson;
const ManagerContext = require('../ManagerContext');
const Menu = require('../Menu');
const MockWrapper = require('./helpers/MockWrapper');
const createMockManager = require('./helpers/createMockManager');
const createManager = require('../createManager');
const el = React.createElement;
describe('<Menu>', function() {
let shallowOptions;
let ambManager;
beforeEach(function() {
ambManager = createMockManager();
shallowOptions = {
wrappingComponent: ManagerContext.Provider,
wrappingComponentProps: { value: ambManager }
};
});
test('closed Menu DOM with only required props and element child', function() {
const menuEl = el(Menu, null, el('div', null, 'foo'));
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
test('no onBlur prop when closeOnBlur is false', function() {
const manager = createManager({ closeOnBlur: false });
manager.isOpen = true;
const shallowOptions = {
wrappingComponent: ManagerContext.Provider,
wrappingComponentProps: { value: manager }
};
const menuEl = el(Menu, null, el('div', null, 'foo'));
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
expect(shallowToJson(wrapper).props).not.toHaveProperty('onBlur');
});
test('open Menu DOM with only required props and element child', function() {
ambManager.isOpen = true;
const menuEl = el(Menu, null, el('div', null, el('div', null, 'foo')));
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
test('closed menu DOM with all possible props and function child', function() {
const childFunction = jest.fn().mockImplementation(function(menuState) {
return 'isOpen = ' + menuState.isOpen;
});
const menuEl = el(
Menu,
{
id: 'foo',
className: 'bar',
style: { bottom: 1 },
tag: 'ul',
'data-something-something': 'seven' // arbitrary prop
},
childFunction
);
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
expect(childFunction).toHaveBeenCalledTimes(1);
expect(childFunction.mock.calls[0]).toEqual([{ isOpen: false }]);
});
test('open menu DOM with all possible props and function child', function() {
ambManager.isOpen = true;
const childFunction = jest.fn().mockImplementation(function(menuState) {
return 'isOpen = ' + menuState.isOpen;
});
const menuEl = el(
Menu,
{
id: 'bar',
className: 'foo',
style: { left: 1 },
tag: 'section'
},
childFunction
);
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
expect(childFunction).toHaveBeenCalledTimes(1);
expect(childFunction.mock.calls[0]).toEqual([{ isOpen: true }]);
});
test('menu updating', function() {
ambManager.menuItems = [1, 2];
const childFunction = jest.fn();
class LittleApp extends React.Component {
state = { open: false };
toggleMenu = () => {
this.setState({ open: !this.state.open });
};
render() {
return el(
MockWrapper,
{ mockManager: ambManager },
el(Menu, null, childFunction)
);
}
}
const wrapper = mount(el(LittleApp));
wrapper.instance().toggleMenu();
expect(ambManager.clearItems).toHaveBeenCalledTimes(1);
});
});
describe('<Menu> rendered via renderToString', function() {
test('does not throw', function() {
const output = ReactDOMServer.renderToString(
el(
MockWrapper,
{ mockManager: createMockManager() },
el(Menu, null, el('div', null, 'foo'))
)
);
expect(output).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,106 @@
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const shallow = require('enzyme').shallow;
const shallowToJson = require('enzyme-to-json').shallowToJson;
const ManagerContext = require('../ManagerContext');
const MenuItem = require('../MenuItem');
const MockWrapper = require('./helpers/MockWrapper');
const createMockKeyEvent = require('./helpers/createMockKeyEvent');
const createMockManager = require('./helpers/createMockManager');
const el = React.createElement;
describe('<MenuItem>', function() {
let shallowOptions;
let ambManager;
beforeEach(function() {
ambManager = createMockManager();
shallowOptions = {
wrappingComponent: ManagerContext.Provider,
wrappingComponentProps: { value: ambManager }
};
});
it('DOM with only required props', function() {
const menuItem = el(MenuItem, null, 'foo');
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
it('DOM with all possible props and element child', function() {
const menuItem = el(
MenuItem,
{
className: 'foobar',
id: 'hogwash',
tag: 'li',
style: { right: '1em' },
text: 'horse',
value: 'lamb',
'data-something-something': 'seven' // arbitrary prop
},
el('a', { href: '#' }, 'foo')
);
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
expect(shallowToJson(wrapper)).toMatchSnapshot();
});
it('click without specified value prop', function() {
const mockEvent = { bee: 'baa' };
const menuItem = el(MenuItem, null, 'foo');
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
wrapper.simulate('click', mockEvent);
expect(ambManager.handleSelection).toHaveBeenCalledTimes(1);
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
'foo',
mockEvent
]);
});
it('click with specified value prop', function() {
const mockEvent = { bee: 'baa' };
const menuItem = el(MenuItem, { value: 'bar' }, 'foo');
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
wrapper.simulate('click', mockEvent);
expect(ambManager.handleSelection).toHaveBeenCalledTimes(1);
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
'bar',
mockEvent
]);
});
it('click with specified value prop', function() {
const mockEnterEvent = createMockKeyEvent('Enter');
const mockSpaceEvent = createMockKeyEvent(' ');
const mockEscapeEvent = createMockKeyEvent('Escape');
const menuItem = el(MenuItem, null, 'foo');
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
wrapper.simulate('keyDown', mockEnterEvent);
wrapper.simulate('keyDown', mockSpaceEvent);
wrapper.simulate('keyDown', mockEscapeEvent);
expect(ambManager.handleSelection).toHaveBeenCalledTimes(2);
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
'foo',
mockEnterEvent
]);
expect(ambManager.handleSelection.mock.calls[1]).toEqual([
'foo',
mockSpaceEvent
]);
});
});
describe('<MenuItem> rendered via renderToString', function() {
it('does not throw', function() {
const output = ReactDOMServer.renderToString(
el(
MockWrapper,
{ mockManager: createMockManager() },
el(MenuItem, null, 'foo')
)
);
expect(output).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Button> DOM with all possible props and element child 1`] = `
<button
aria-disabled={true}
aria-expanded={false}
aria-haspopup={true}
className="bar"
data-something-something="seven"
disabled={true}
id="foo"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
style={
Object {
"top": 2,
}
}
tabIndex=""
>
<span>
hooha
</span>
</button>
`;
exports[`<Button> DOM with only required props and text child 1`] = `
<span
aria-expanded={false}
aria-haspopup={true}
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex="0"
>
foo
</span>
`;
exports[`<Button> rendered via renderToString does not throw 1`] = `"<div><span role=\\"button\\" tabindex=\\"0\\" aria-haspopup=\\"true\\" aria-expanded=\\"false\\">foo</span></div>"`;

View File

@@ -0,0 +1,54 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Menu> closed Menu DOM with only required props and element child 1`] = `""`;
exports[`<Menu> closed menu DOM with all possible props and function child 1`] = `
<ul
className="bar"
data-something-something="seven"
id="foo"
onKeyDown={[Function]}
role="menu"
style={
Object {
"bottom": 1,
}
}
tabIndex={-1}
>
isOpen = false
</ul>
`;
exports[`<Menu> open Menu DOM with only required props and element child 1`] = `
<div
onKeyDown={[Function]}
role="menu"
tabIndex={-1}
>
<div>
<div>
foo
</div>
</div>
</div>
`;
exports[`<Menu> open menu DOM with all possible props and function child 1`] = `
<section
className="foo"
id="bar"
onKeyDown={[Function]}
role="menu"
style={
Object {
"left": 1,
}
}
tabIndex={-1}
>
isOpen = true
</section>
`;
exports[`<Menu> rendered via renderToString does not throw 1`] = `"<div></div>"`;

View File

@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<MenuItem> DOM with all possible props and element child 1`] = `
<li
className="foobar"
data-something-something="seven"
id="hogwash"
onClick={[Function]}
onKeyDown={[Function]}
role="menuitem"
style={
Object {
"right": "1em",
}
}
tabIndex="-1"
>
<a
href="#"
>
foo
</a>
</li>
`;
exports[`<MenuItem> DOM with only required props 1`] = `
<div
onClick={[Function]}
onKeyDown={[Function]}
role="menuitem"
tabIndex="-1"
>
foo
</div>
`;
exports[`<MenuItem> rendered via renderToString does not throw 1`] = `"<div><div role=\\"menuitem\\" tabindex=\\"-1\\">foo</div></div>"`;

View File

@@ -0,0 +1,190 @@
/* globals Promise */
var createManager = require('../createManager');
var createMockKeyEvent = require('./helpers/createMockKeyEvent');
var mockNode = document.createElement('button');
var nodeOne = document.createElement('button');
nodeOne.focus = jest.fn();
var nodeTwo = document.createElement('button');
nodeTwo.focus = jest.fn();
document.body.appendChild(nodeOne);
document.body.appendChild(nodeTwo);
function createManagerWithMockedElements(options) {
var manager = createManager(options);
manager.focusGroup.addMember({
node: nodeOne,
text: 'first'
});
manager.focusGroup.addMember({
node: nodeTwo,
text: 'second'
});
manager.button = {
ref: { current: mockNode },
setState: jest.fn()
};
manager.menu = {
setState: jest.fn()
};
manager.focusItem = jest.fn();
return manager;
}
describe('createManager', function() {
it('initalizes', function() {
var manager = createManagerWithMockedElements();
expect(manager.isOpen).toBe(false);
expect(manager.options.closeOnSelection).toBeTruthy();
expect(manager.options.closeOnBlur).toBeTruthy();
});
it('Manager#update', function() {
var manager = createManagerWithMockedElements({
onMenuToggle: jest.fn()
});
manager.update();
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
expect(manager.menu.setState.mock.calls[0]).toEqual([
{ isOpen: manager.isOpen }
]);
expect(manager.button.setState).toHaveBeenCalledTimes(1);
expect(manager.button.setState.mock.calls[0]).toEqual([
{ menuOpen: manager.isOpen }
]);
expect(manager.options.onMenuToggle).toHaveBeenCalledTimes(1);
expect(manager.options.onMenuToggle.mock.calls[0]).toEqual([
{ isOpen: manager.isOpen }
]);
});
it('Manager#openMenu without focusing in menu', function() {
var manager = createManagerWithMockedElements();
manager.openMenu({ focusMenu: false });
expect(manager.isOpen).toBe(true);
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: true }]);
expect(manager.button.setState).toHaveBeenCalledTimes(1);
expect(manager.button.setState.mock.calls[0]).toEqual([{ menuOpen: true }]);
return new Promise(function(resolve) {
setTimeout(function() {
expect(manager.focusItem).toHaveBeenCalledTimes(0);
resolve();
}, 0);
});
});
it('Manager#openMenu focusing in menu', function() {
var manager = createManagerWithMockedElements();
manager.openMenu();
expect(manager.isOpen).toBe(true);
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: true }]);
expect(manager.button.setState).toHaveBeenCalledTimes(1);
expect(manager.button.setState.mock.calls[0]).toEqual([{ menuOpen: true }]);
return new Promise(function(resolve) {
setTimeout(function() {
expect(manager.focusItem).toHaveBeenCalledTimes(1);
expect(manager.focusItem.mock.calls[0]).toEqual([0]);
resolve();
}, 0);
});
});
it('Manager#closeMenu focusing on button', function() {
mockNode.focus = jest.fn();
var manager = createManagerWithMockedElements();
manager.isOpen = true;
manager.closeMenu({ focusButton: true });
expect(manager.isOpen).toBe(false);
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: false }]);
expect(manager.button.setState).toHaveBeenCalledTimes(1);
expect(manager.button.setState.mock.calls[0]).toEqual([
{ menuOpen: false }
]);
expect(mockNode.focus).toHaveBeenCalledTimes(1);
});
it('Manager#closeMenu without focusing on button', function() {
mockNode.focus = jest.fn();
var manager = createManagerWithMockedElements();
manager.isOpen = true;
manager.closeMenu({ focusButton: false });
expect(mockNode.focus).not.toHaveBeenCalled();
});
it('Manager#toggleMenu when closed', function() {
var manager = createManagerWithMockedElements();
manager.openMenu = jest.fn();
manager.closeMenu = jest.fn();
manager.toggleMenu();
expect(manager.openMenu).toHaveBeenCalledTimes(1);
expect(manager.closeMenu).not.toHaveBeenCalled();
});
it('Manager#toggleMenu when open', function() {
var manager = createManagerWithMockedElements();
manager.isOpen = true;
manager.openMenu = jest.fn();
manager.closeMenu = jest.fn();
manager.toggleMenu();
expect(manager.openMenu).not.toHaveBeenCalled();
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
});
it('Manager#handleSelection A', function() {
var mockOnSelection = jest.fn();
var manager = createManagerWithMockedElements({
onSelection: mockOnSelection
});
manager.closeMenu = jest.fn();
manager.handleSelection('foo', { bar: 1 });
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
expect(manager.closeMenu.mock.calls[0]).toEqual([{ focusButton: true }]);
expect(mockOnSelection).toHaveBeenCalledTimes(1);
expect(mockOnSelection.mock.calls[0]).toEqual(['foo', { bar: 1 }]);
});
it('Manager#handleSelection B', function() {
var mockOnSelection = jest.fn();
var manager = createManagerWithMockedElements({
onSelection: mockOnSelection,
closeOnSelection: false
});
manager.closeMenu = jest.fn();
manager.handleSelection('foo', { bar: 1 });
expect(manager.closeMenu).not.toHaveBeenCalled();
expect(mockOnSelection).toHaveBeenCalledTimes(1);
expect(mockOnSelection.mock.calls[0]).toEqual(['foo', { bar: 1 }]);
});
it('Manager#handleMenuKey on closed menu', function() {
var escapeEvent = createMockKeyEvent('Escape');
var manager = createManagerWithMockedElements();
manager.closeMenu = jest.fn();
manager.handleMenuKey(escapeEvent);
expect(escapeEvent.preventDefault).not.toHaveBeenCalled();
expect(manager.closeMenu).not.toHaveBeenCalled();
});
it('Manager#handleMenuKey on open menu', function() {
var escapeEvent = createMockKeyEvent('Escape');
var manager = createManagerWithMockedElements();
manager.isOpen = true;
manager.closeMenu = jest.fn();
manager.handleMenuKey(escapeEvent);
expect(escapeEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
expect(manager.closeMenu.mock.calls[0]).toEqual([{ focusButton: true }]);
});
});

View File

@@ -0,0 +1,24 @@
const React = require('react');
const PropTypes = require('prop-types');
const ManagerContext = require('../../ManagerContext');
class MockWrapper extends React.Component {
static propTypes = {
mockManager: PropTypes.object.isRequired,
};
constructor(props) {
super(props);
this.manager = this.props.mockManager;
}
render() {
return React.createElement(
ManagerContext.Provider,
{ value: this.props.mockManager },
React.createElement('div', null, this.props.children)
);
}
}
module.exports = MockWrapper;

View File

@@ -0,0 +1,7 @@
module.exports = function(key, keyCode) {
return {
key: key,
keyCode: keyCode,
preventDefault: jest.fn(),
};
};

View File

@@ -0,0 +1,22 @@
module.exports = function() {
return {
isOpen: false,
toggleMenu: jest.fn(),
handleMenuKey: jest.fn(),
moveFocusDown: jest.fn(),
openMenu: jest.fn(),
handleKeyDown: jest.fn(),
handleClick: jest.fn(),
handleSelection: jest.fn(),
handleButtonNonArrowKey: jest.fn(),
focusItem: jest.fn(),
menuItems: [1, 2],
clearItems: jest.fn(),
currentFocus: -1,
addItem: jest.fn(),
options: {
closeOnBlur: true,
closeOnSelection: true
}
};
}

View File

@@ -0,0 +1,5 @@
import './raf';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });

View File

@@ -0,0 +1,3 @@
global.requestAnimationFrame = (callback) => {
setTimeout(callback, 0);
};