import popper.js
Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
parent
615dc56d16
commit
16fb2bb919
241 changed files with 34099 additions and 0 deletions
|
|
@ -0,0 +1,299 @@
|
|||
import Popper from '../../src/index.js';
|
||||
import makePopperFactory from '../utils/makePopperFactory';
|
||||
import makeConnectedElement from '@popperjs/test-utils/utils/makeConnectedElement';
|
||||
import makeConnectedScrollElement from '@popperjs/test-utils/utils/makeConnectedScrollElement';
|
||||
import makeElement from '@popperjs/test-utils/utils/makeElement';
|
||||
import '@popperjs/test-utils/setup';
|
||||
|
||||
[true, false].forEach((positionFixed) => {
|
||||
|
||||
describe('[lifecycle]' + (positionFixed ? ' Fixed' : ''), () => {
|
||||
|
||||
beforeEach(function(){
|
||||
Popper.Defaults.positionFixed = positionFixed;
|
||||
});
|
||||
|
||||
const makePopper = makePopperFactory();
|
||||
|
||||
describe('on creation', () => {
|
||||
it('adds a resize event listener', () => {
|
||||
spyOn(window, 'addEventListener');
|
||||
|
||||
const { state } = makePopper(
|
||||
makeConnectedElement(),
|
||||
makeConnectedElement()
|
||||
);
|
||||
|
||||
expect(window.addEventListener.calls.argsFor(0)).toEqual([
|
||||
'resize',
|
||||
state.updateBound,
|
||||
{ passive: true },
|
||||
]);
|
||||
});
|
||||
|
||||
it('adds a scroll event listener to window when boundariesElement is viewport', () => {
|
||||
spyOn(window, 'addEventListener');
|
||||
|
||||
const {
|
||||
state,
|
||||
} = makePopper(makeConnectedElement(), makeConnectedElement(), {
|
||||
boundariesElement: 'viewport',
|
||||
});
|
||||
|
||||
expect(window.addEventListener.calls.argsFor(1)).toEqual([
|
||||
'scroll',
|
||||
state.updateBound,
|
||||
{ passive: true },
|
||||
]);
|
||||
});
|
||||
|
||||
it('adds a scroll event listener to the closest scroll ancestor of reference when boundariesElement is an element', () => {
|
||||
const boundariesElement = makeConnectedElement();
|
||||
const scrollAncestor = document.createElement('div');
|
||||
const reference = document.createElement('div');
|
||||
const popper = document.createElement('div');
|
||||
|
||||
boundariesElement.appendChild(scrollAncestor);
|
||||
scrollAncestor.appendChild(reference);
|
||||
scrollAncestor.appendChild(popper);
|
||||
|
||||
scrollAncestor.style.overflow = 'scroll';
|
||||
|
||||
spyOn(scrollAncestor, 'addEventListener');
|
||||
const { state } = makePopper(reference, popper, {
|
||||
boundariesElement: boundariesElement,
|
||||
});
|
||||
|
||||
expect(scrollAncestor.addEventListener.calls.allArgs()).toEqual([
|
||||
['scroll', state.updateBound, { passive: true }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not add resize/scroll event if eventsEnabled option is set to false', () => {
|
||||
const {
|
||||
state,
|
||||
} = makePopper(makeConnectedElement(), makeConnectedElement(), {
|
||||
eventsEnabled: false,
|
||||
});
|
||||
|
||||
expect(state.eventsEnabled).toBe(false);
|
||||
expect(state.updateBound).toBeUndefined();
|
||||
expect(state.scrollElement).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('on update', () => {
|
||||
it('should call update callback', done => {
|
||||
const popperElement = makeConnectedElement();
|
||||
|
||||
let isOnCreateCalled = false;
|
||||
|
||||
new Popper(makeConnectedElement(), popperElement, {
|
||||
onCreate: data => {
|
||||
isOnCreateCalled = true;
|
||||
data.instance.scheduleUpdate();
|
||||
},
|
||||
onUpdate: () => {
|
||||
// makes sure it's executed after `onCreate`
|
||||
expect(isOnCreateCalled).toBe(true);
|
||||
// makes sure it's executed
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('on destroy', () => {
|
||||
|
||||
const mockStyles = {
|
||||
top: '100px',
|
||||
left: '100px',
|
||||
right: '100px',
|
||||
bottom: '100px',
|
||||
position: 'absolute',
|
||||
transform: 'translate3d(100px, 100px, 0)',
|
||||
willChange: 'transform',
|
||||
}
|
||||
|
||||
it('removes the resize event listener from window', () => {
|
||||
spyOn(window, 'removeEventListener');
|
||||
|
||||
const instance = new Popper(
|
||||
makeConnectedElement(),
|
||||
makeConnectedElement()
|
||||
);
|
||||
const { updateBound } = instance.state;
|
||||
instance.destroy();
|
||||
|
||||
expect(window.removeEventListener.calls.argsFor(0)).toEqual([
|
||||
'resize',
|
||||
updateBound,
|
||||
]);
|
||||
});
|
||||
|
||||
it('removes the scroll event listener from window', () => {
|
||||
spyOn(window, 'removeEventListener');
|
||||
|
||||
const instance = new Popper(
|
||||
makeConnectedElement(),
|
||||
makeConnectedElement()
|
||||
);
|
||||
const { updateBound } = instance.state;
|
||||
instance.destroy();
|
||||
|
||||
expect(window.removeEventListener.calls.argsFor(1)).toEqual([
|
||||
'scroll',
|
||||
updateBound,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should clean up the popper element\'s styles if modifiers.applyStyle is enabled', () => {
|
||||
const popperElement = makeConnectedElement();
|
||||
|
||||
for (const key in mockStyles) {
|
||||
if (mockStyles.hasOwnProperty(key)) {
|
||||
popperElement.style[key] = mockStyles[key];
|
||||
}
|
||||
}
|
||||
|
||||
const instance = new Popper(makeConnectedElement(), popperElement, {
|
||||
modifiers: { applyStyle: { enabled: true } },
|
||||
});
|
||||
|
||||
instance.destroy();
|
||||
|
||||
for (const key in mockStyles) {
|
||||
if (mockStyles.hasOwnProperty(key)) {
|
||||
expect(popperElement.style[key]).toBe('');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should not modify the popper element\'s styles if modifiers.applyStyle is disabled', () => {
|
||||
const popperElement = makeConnectedElement();
|
||||
|
||||
for (const key in mockStyles) {
|
||||
if (mockStyles.hasOwnProperty(key)) {
|
||||
popperElement.style[key] = mockStyles[key];
|
||||
}
|
||||
}
|
||||
|
||||
const instance = new Popper(makeConnectedElement(), popperElement, {
|
||||
modifiers: { applyStyle: { enabled: false } },
|
||||
});
|
||||
|
||||
instance.destroy();
|
||||
|
||||
for (const key in mockStyles) {
|
||||
if (mockStyles.hasOwnProperty(key)) {
|
||||
expect(popperElement.style[key]).not.toBe('');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should not call update after destroy', () => {
|
||||
let isUpdateCalled = false;
|
||||
|
||||
const popperElement = makeConnectedElement();
|
||||
|
||||
const instance = new Popper(makeConnectedElement(), popperElement, {
|
||||
onUpdate: () => {
|
||||
isUpdateCalled = true;
|
||||
},
|
||||
});
|
||||
instance.update();
|
||||
instance.destroy();
|
||||
expect(isUpdateCalled).toBe(false);
|
||||
});
|
||||
|
||||
describe('when boundariesElement is not `window` and the scroll parent is not `window`', () => {
|
||||
it('removes the scroll event listener from the scroll parent', () => {
|
||||
const boundariesElement = makeConnectedScrollElement();
|
||||
const reference = boundariesElement.appendChild(makeElement());
|
||||
const popper = boundariesElement.appendChild(makeElement());
|
||||
|
||||
spyOn(boundariesElement, 'removeEventListener');
|
||||
|
||||
const instance = new Popper(reference, popper, {
|
||||
boundariesElement: boundariesElement,
|
||||
});
|
||||
const { updateBound } = instance.state;
|
||||
instance.destroy();
|
||||
|
||||
expect(boundariesElement.removeEventListener.calls.allArgs()).toEqual([
|
||||
['scroll', updateBound],
|
||||
]);
|
||||
});
|
||||
|
||||
describe('when the reference is disconnected from the DOM', () => {
|
||||
it('removes the scroll event listener from the scroll parent when the reference is disconnected from the DOM', () => {
|
||||
const boundariesElement = makeConnectedScrollElement();
|
||||
const reference = boundariesElement.appendChild(makeElement());
|
||||
const popper = boundariesElement.appendChild(makeElement());
|
||||
|
||||
spyOn(boundariesElement, 'removeEventListener');
|
||||
|
||||
const instance = new Popper(reference, popper, {
|
||||
boundariesElement: boundariesElement,
|
||||
});
|
||||
const { updateBound } = instance.state;
|
||||
|
||||
boundariesElement.removeChild(reference);
|
||||
instance.destroy();
|
||||
|
||||
expect(
|
||||
boundariesElement.removeEventListener.calls.allArgs()
|
||||
).toEqual([['scroll', updateBound]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods: enableEventListeners/disableEventListeners', () => {
|
||||
it('enableEventListeners', () => {
|
||||
spyOn(window, 'addEventListener');
|
||||
const instance = makePopper(
|
||||
makeConnectedElement(),
|
||||
makeConnectedElement(),
|
||||
{ eventsEnabled: false }
|
||||
);
|
||||
|
||||
instance.enableEventListeners();
|
||||
expect(window.addEventListener.calls.count()).toEqual(2);
|
||||
expect(window.addEventListener.calls.argsFor(0)).toEqual([
|
||||
'resize',
|
||||
instance.state.updateBound,
|
||||
{ passive: true },
|
||||
]);
|
||||
expect(window.addEventListener.calls.argsFor(1)).toEqual([
|
||||
'scroll',
|
||||
instance.state.updateBound,
|
||||
{ passive: true },
|
||||
]);
|
||||
expect(instance.state.eventsEnabled).toBe(true);
|
||||
});
|
||||
|
||||
it('disableEventListeners', () => {
|
||||
spyOn(window, 'removeEventListener');
|
||||
const instance = makePopper(
|
||||
makeConnectedElement(),
|
||||
makeConnectedElement()
|
||||
);
|
||||
const { updateBound } = instance.state;
|
||||
|
||||
instance.disableEventListeners();
|
||||
expect(window.removeEventListener.calls.argsFor(0)).toEqual([
|
||||
'resize',
|
||||
updateBound,
|
||||
]);
|
||||
expect(window.removeEventListener.calls.argsFor(1)).toEqual([
|
||||
'scroll',
|
||||
updateBound,
|
||||
]);
|
||||
expect(instance.state.eventsEnabled).toBe(false);
|
||||
expect(instance.state.updateBound).toBe(null);
|
||||
expect(instance.state.scrollElement).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue