wix-style-react
Version:
wix-style-react
630 lines (629 loc) • 24.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _Popover = _interopRequireDefault(require("../Popover"));
var _PopoverCore = require("../PopoverCore/PopoverCore");
var _unit = require("../../test-utils/utils/unit");
var _PopoverUni = require("../Popover.uni.driver");
var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/Popover/tests/Popover.spec.tsx",
_this = void 0;
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var renderPopover = function renderPopover(props) {
var content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Content';
return /*#__PURE__*/React.createElement(_Popover.default, (0, _extends2.default)({}, props, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 15,
columnNumber: 3
}
}), /*#__PURE__*/React.createElement(_Popover.default.Element, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 16,
columnNumber: 5
}
}, /*#__PURE__*/React.createElement("div", {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 17,
columnNumber: 7
}
}, "Element")), /*#__PURE__*/React.createElement(_Popover.default.Content, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 19,
columnNumber: 5
}
}, /*#__PURE__*/React.createElement("div", {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 20,
columnNumber: 7
}
}, content)));
};
describe('Popover', () => {
var render = (0, _unit.createAsyncRendererWithUniDriver)(_PopoverUni.popoverUniDriverFactory);
describe('props', () => {
describe('shown', () => {
it("doesn't display popup when shown={false}", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
placement: 'bottom',
shown: false
};
var {
driver
} = yield render(renderPopover(props));
expect(yield driver.isTargetElementExists()).toBe(true);
expect(yield driver.isContentElementExists()).toBe(false);
}));
it("displays popup when shown={true}", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
placement: 'bottom',
shown: true
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
}));
});
describe('onMouseEnter & onMouseLeave', () => {
it("calls mouseEnter and mouseLeave callbacks", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onMouseEnter = jest.fn();
var onMouseLeave = jest.fn();
var props = {
onMouseEnter,
onMouseLeave
};
var {
driver
} = yield render(renderPopover(props));
yield driver.mouseEnter();
expect(onMouseEnter).toHaveBeenCalled();
yield driver.mouseLeave();
expect(onMouseLeave).toBeCalled();
}));
});
describe('onClick', () => {
it("calls onClick callback", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onClick = jest.fn();
var props = {
onClick
};
var {
driver
} = yield render(renderPopover(props));
yield driver.click();
expect(onClick).toBeCalled();
}));
});
describe('onClickOutside', () => {
it('should be triggered when outside of the popover is called', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onClickOutside = jest.fn();
var props = {
onClickOutside,
shown: true
};
var {
driver
} = yield render(renderPopover(props));
yield driver.clickOutside();
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
return expect(onClickOutside).toBeCalled();
}));
}));
it('should not trigger onClickOutside when clicking inside with an excluded class', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onClickOutside = jest.fn();
var props = {
onClickOutside,
shown: false,
excludeClass: 'excludeClass'
};
var {
driver
} = yield render(renderPopover(props));
yield driver.click();
expect(onClickOutside).not.toBeCalled();
}));
});
describe('disableClickOutsideWhenClosed', () => {
it('should be triggered when outside of the popover is called', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onClickOutside = jest.fn();
var props = {
shown: true,
onClickOutside,
disableClickOutsideWhenClosed: true
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
yield driver.clickOutside();
}));
expect(onClickOutside).toBeCalled();
}));
it('should *not* be triggered when outside of the popover is called and the popover is *not* shown', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onClickOutside = jest.fn();
var props = {
shown: false,
onClickOutside,
disableClickOutsideWhenClosed: true
};
var {
driver
} = yield render(renderPopover(props));
yield driver.clickOutside();
expect(onClickOutside).not.toBeCalled();
}));
});
describe('dataHook', () => {
it('should be found on target element container', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
appendTo: 'window',
dataHook: 'random'
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var target = yield driver.getTargetElement();
expect(target.parentNode.getAttribute('data-hook')).toBe('random');
}));
}));
it('should construct data-content-hook', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
appendTo: 'window',
dataHook: 'random'
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var target = yield driver.getTargetElement();
expect(target.parentNode.getAttribute('data-content-hook')).toMatch(/popover-content-random-/);
}));
}));
it('should apply data-content-element on content element', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
appendTo: 'window',
dataHook: 'random'
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
var content = yield driver.getContentElement();
expect(content.getAttribute('data-content-element')).toMatch(/popover-content-random-/);
}));
it('should not override portal component data-hook', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
appendTo: 'window',
dataHook: 'random'
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
var content = yield driver.getContentElement();
expect(content.parentNode.getAttribute('data-hook')).toBe('popover-portal');
}));
});
describe('customArrow', () => {
it('should display a custom arrow element', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var customArrow = (placement, arrowProps) => /*#__PURE__*/React.createElement("p", (0, _extends2.default)({
"data-test": "custom-arrow",
"data-placement": placement
}, arrowProps, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 214,
columnNumber: 11
}
}));
var props = {
shown: true,
showArrow: true,
customArrow,
placement: 'top'
};
var {
driver,
container
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
var arrowElement = container.querySelector('[data-test="custom-arrow"]');
expect(!!arrowElement).toBe(true);
}));
});
describe('moveArrowTo', () => {
it("offsets the popup arrow by specified amount", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
showArrow: true,
moveArrowTo: 10
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect((yield driver.getArrowOffset()).left).toBe('10px');
}));
}));
});
describe('timeout', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it("remove timeout on close [when] given a timeout={0}", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var timeout = {
timeout: 0
};
var props = _objectSpread({
shown: true
}, timeout);
var {
driver,
rerender
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
yield rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: false
})));
expect(yield driver.isContentElementExists()).toBe(false);
}));
it('adds timeout of 100ms on close [when] given a timeout={100}', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var timeout = 100;
var props = {
shown: true,
timeout
};
var {
driver,
rerender
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
yield rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: false
})));
expect(yield driver.isContentElementExists()).toBe(true);
yield (0, _unit.act)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
jest.advanceTimersByTime(timeout);
}));
expect(yield driver.isContentElementExists()).toBe(false);
}));
});
describe('hideDelay', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it("should close after hideDelay", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var timeout = 500;
var props = {
shown: true,
hideDelay: timeout
};
var {
driver,
rerender
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
yield rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: false
})));
expect(yield driver.isContentElementExists()).toBe(true);
yield (0, _unit.act)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
jest.advanceTimersByTime(timeout);
}));
expect(yield driver.isContentElementExists()).toBe(false);
}));
it("should not update delay until the popover visibillity has fully changed", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var timeout = 500;
var props = {
shown: true,
hideDelay: timeout
};
var {
driver,
rerender
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
yield rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: false,
hideDelay: 100
})));
expect(yield driver.isContentElementExists()).toBe(true);
yield (0, _unit.act)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
jest.advanceTimersByTime(timeout);
}));
expect(yield driver.isContentElementExists()).toBe(false);
}));
});
describe('showDelay', () => {
it("should show the content immediately on first render", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
showDelay: 100
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
}));
it("should open after showDelay", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var timeout = {
timeout: 500
};
var props = {
shown: false,
showDelay: 100
};
var {
driver,
rerender
} = yield render(renderPopover(props));
expect(yield driver.isContentElementExists()).toBe(false);
yield rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: true
})));
expect(yield driver.isContentElementExists()).toBe(false);
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}), timeout);
}));
});
describe('onShow', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it('should call the onShow callback when popover is shown', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onShow = jest.fn();
var props = {
shown: false,
onShow
};
var {
driver,
rerender
} = yield render(renderPopover(props));
expect(yield driver.isContentElementExists()).toBe(false);
expect(onShow).not.toHaveBeenCalled();
yield (0, _unit.act)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: true
})));
}));
expect(yield driver.isContentElementExists()).toBe(true);
expect(onShow).toHaveBeenCalledTimes(1);
}));
it('should call the onShow callback when popover is shown after a delay', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var onShow = jest.fn();
var showDelay = 100;
var props = {
shown: false,
showDelay,
onShow
};
var {
driver,
rerender
} = yield render(renderPopover(props));
expect(yield driver.isContentElementExists()).toBe(false);
expect(onShow).not.toHaveBeenCalled();
rerender(renderPopover(_objectSpread(_objectSpread({}, props), {}, {
shown: true
})));
expect(yield driver.isContentElementExists()).toBe(false);
expect(onShow).not.toHaveBeenCalled();
yield (0, _unit.act)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
jest.advanceTimersByTime(showDelay + 10);
}));
expect(yield driver.isContentElementExists()).toBe(true);
expect(onShow).toHaveBeenCalledTimes(1);
}));
});
});
describe('Accessibility', () => {
it('should pass aria attrs to content wrapper', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var role = 'someRole';
var ariaAttributes = {
'aria-label': 'someAriaLabel',
'aria-labelledby': 'someAriaLabelledby',
'aria-describedby': 'someAriaDescribedby'
};
var props = _objectSpread({
shown: true,
role
}, ariaAttributes);
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
var contentElement = yield driver.getContentElement();
expect(contentElement.getAttribute('role')).toBe(role);
for (var [ariaAttr, ariaAttrValue] of Object.entries(ariaAttributes)) {
expect(contentElement.getAttribute(ariaAttr)).toBe(ariaAttrValue);
}
}));
it('should apply id attribute only on popover content', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var ariaId = 'test-labelled';
var {
driver,
container
} = yield render(renderPopover({
id: ariaId,
shown: true
}));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(container.querySelectorAll("[id=\"".concat(ariaId, "\"]"))).toHaveLength(1);
}));
expect(yield driver.getContentElement()).toHaveProperty('id', ariaId);
}));
});
describe('Popper update behaviour', () => {
it("should update popper's position when props are chaning", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var updatePositionSpy = jest.spyOn(_PopoverCore.PopoverCore.prototype, 'updatePosition');
var {
rerender
} = yield render(renderPopover({
shown: true
}));
yield rerender(renderPopover({
shown: true
}, 'New Content'));
expect(updatePositionSpy).toHaveBeenCalledTimes(2);
updatePositionSpy.mockRestore();
}));
it("should not directly update popper's position when the visibillity hasn't changed", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var updatePositionSpy = jest.spyOn(_PopoverCore.PopoverCore.prototype, 'updatePosition');
var {
rerender
} = yield render(renderPopover({
hideDelay: 10,
showDelay: 10,
shown: false
}));
yield rerender(renderPopover({
hideDelay: 10,
showDelay: 10,
shown: true
}));
yield rerender(renderPopover({
hideDelay: 10,
showDelay: 10,
shown: false
}));
expect(updatePositionSpy).toHaveBeenCalledTimes(1);
updatePositionSpy.mockRestore();
}));
});
describe('Portal and containment', () => {
it('should render content inside portal [when] appendTo = window', /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: true,
appendTo: 'window'
};
var {
driver
} = yield render(renderPopover(props));
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(yield driver.isContentElementExists()).toBe(true);
}));
var portalElement = document.body.querySelector('[data-hook="popover-portal"]');
expect(!!portalElement).toBe(true);
}));
it("renders an empty portal when closed", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: false,
appendTo: 'window'
};
yield render(renderPopover(props));
var portalElement = document.body.querySelector('[data-hook="popover-portal"]');
expect(!!portalElement).toBe(true);
}));
it("removes portal on unmount", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var props = {
shown: false,
appendTo: 'window'
};
var {
unmount
} = yield render(renderPopover(props));
var portalElement = document.body.querySelector('[data-hook="popover-portal"]');
expect(!!portalElement).toBe(true);
unmount();
var portalElementUnounted = document.body.querySelector('[data-hook="popover-portal"]');
expect(!!portalElementUnounted).toBe(false);
}));
it("adds the portal to the closest scrollable element when appendTo=\"scrollParent\"", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var _document$body$queryS;
var srollableHook = 'scrollable-element';
var props = {
shown: false,
appendTo: 'scrollParent'
};
yield render(/*#__PURE__*/React.createElement("div", {
"data-hook": srollableHook,
style: {
overflow: 'scroll'
},
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 573,
columnNumber: 9
}
}, /*#__PURE__*/React.createElement("div", {
style: {
overflow: 'visible'
},
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 574,
columnNumber: 11
}
}, renderPopover(props))));
var parentElementHook = (_document$body$queryS = document.body.querySelector('[data-hook="popover-portal"]')) == null || (_document$body$queryS = _document$body$queryS.parentElement) == null ? void 0 : _document$body$queryS.getAttribute('data-hook');
expect(parentElementHook).toBe(srollableHook);
}));
it("should update the portal's styles when updated", /*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
var className = 'some-class';
var props = {
shown: true,
appendTo: 'window',
className
};
yield render(renderPopover(props));
var portalElement = document.body.querySelector('[data-hook="popover-portal"]');
yield (0, _unit.waitFor)(/*#__PURE__*/(0, _asyncToGenerator2.default)(function* () {
expect(portalElement == null ? void 0 : portalElement.classList).toContain(className);
}));
}));
});
});
//# sourceMappingURL=Popover.spec.js.map