UNPKG

@nguyenmv2/buy-button

Version:

BuyButton.js allows merchants to build Shopify interfaces into any website

192 lines (153 loc) 6.45 kB
import {trapFocus, removeTrapFocus} from '../../src/utils/focus'; describe('Focus utils', () => { let node; let firstEl; let middleEl; let lastEl; beforeEach(() => { node = document.createElement('div'); firstEl = document.createElement('button'); middleEl = document.createElement('input'); lastEl = document.createElement('select'); node.appendChild(firstEl); node.appendChild(middleEl); node.appendChild(lastEl); document.body.appendChild(node); }); afterEach(() => { document.body.removeChild(node); }); describe('trapFocus', () => { it('focuses the first element', () => { const focusSpy = sinon.spy(); firstEl.focus = focusSpy; trapFocus(node); assert.calledOnce(focusSpy); }); describe('Focus events', () => { let addEventListenerSpy; let removeEventListenerSpy; beforeEach(() => { addEventListenerSpy = sinon.spy(); removeEventListenerSpy = sinon.spy(); node.addEventListener = addEventListenerSpy; node.removeEventListener = removeEventListenerSpy; trapFocus(node); }); it('adds focusin and focusout event handlers', () => { assert.calledTwice(addEventListenerSpy); assert.calledWith(addEventListenerSpy.firstCall, 'focusout'); assert.calledWith(addEventListenerSpy.secondCall, 'focusin'); }); it('adds a keydown event listener if the focusin event handler is called on the first focusable element', () => { const mockEvent = { target: firstEl, }; addEventListenerSpy.getCall(1).args[1](mockEvent); assert.calledThrice(addEventListenerSpy); assert.calledWith(addEventListenerSpy.thirdCall, 'keydown'); }); it('adds a keydown event listener if the focusin event handler is called on the last focusable element', () => { const mockEvent = { target: lastEl, }; addEventListenerSpy.getCall(1).args[1](mockEvent); assert.calledThrice(addEventListenerSpy); assert.calledWith(addEventListenerSpy.thirdCall, 'keydown'); }); it('does not add a keydown event listener if the focusin event handler is called on a focusable element that is not first or last', () => { const mockEvent = { target: middleEl, }; addEventListenerSpy.getCall(1).args[1](mockEvent); assert.calledTwice(addEventListenerSpy); }); it('removes the keydown event if the focusout event handle is called', () => { removeEventListenerSpy.resetHistory(); addEventListenerSpy.getCall(0).args[1](); assert.calledOnce(removeEventListenerSpy); assert.calledWith(removeEventListenerSpy.firstCall, 'keydown'); }); }); describe('removeTrapFocus call', () => { it('removes the focusin, focusout, and keydown event handlers from the node provided if they currently exist', () => { trapFocus(node); const removeEventListenerSpy = sinon.spy(); node.removeEventListener = removeEventListenerSpy; trapFocus(node); assert.calledThrice(removeEventListenerSpy); assert.calledWith(removeEventListenerSpy.firstCall, 'focusin'); assert.calledWith(removeEventListenerSpy.secondCall, 'focusout'); assert.calledWith(removeEventListenerSpy.thirdCall, 'keydown'); }); }); describe('Keydown event', () => { let addEventListenerSpy; let preventDefaultSpy; let focusinHandler; let keydownHandler; beforeEach(() => { preventDefaultSpy = sinon.spy(); addEventListenerSpy = sinon.spy(node, 'addEventListener'); trapFocus(node); focusinHandler = addEventListenerSpy.getCall(1).args[1]; }); describe('First element', () => { beforeEach(() => { focusinHandler({ target: firstEl, }); keydownHandler = addEventListenerSpy.getCall(2).args[1]; }); it('focuses the last element if shift+tab is pressed when focused on the first element', () => { const focusSpy = sinon.spy(); lastEl.focus = focusSpy; keydownHandler({keyCode: 9, shiftKey: true, target: firstEl, preventDefault: preventDefaultSpy}); assert.calledOnce(focusSpy); assert.calledOnce(preventDefaultSpy); }); it('does not focus the last element if a non shift+tab key is pressed when focused on the first element', () => { const focusSpy = sinon.spy(); lastEl.focus = focusSpy; keydownHandler({keyCode: 10, shiftKey: true, target: firstEl, preventDefault: preventDefaultSpy}); assert.notCalled(focusSpy); assert.notCalled(preventDefaultSpy); }); }); describe('Last element', () => { beforeEach(() => { focusinHandler({ target: lastEl, }); keydownHandler = addEventListenerSpy.getCall(2).args[1]; }); it('focuses the first element if tab is pressed when focused on the last element', () => { const focusSpy = sinon.spy(); firstEl.focus = focusSpy; keydownHandler({keyCode: 9, shiftKey: false, target: lastEl, preventDefault: preventDefaultSpy}); assert.calledOnce(focusSpy); assert.calledOnce(preventDefaultSpy); }); it('does not focus the first element if a non tab key is pressed when focused on the last element', () => { const focusSpy = sinon.spy(); firstEl.focus = focusSpy; keydownHandler({keyCode: 10, shiftKey: false, target: lastEl, preventDefault: preventDefaultSpy}); assert.notCalled(focusSpy); assert.notCalled(preventDefaultSpy); }); }); }); }); describe('removeTrapFocus', () => { it('removes the focusin, focusout, and keydown event handlers from the node provided', () => { trapFocus(node); const removeEventListenerSpy = sinon.spy(); node.removeEventListener = removeEventListenerSpy; removeTrapFocus(node); assert.calledThrice(removeEventListenerSpy); assert.calledWith(removeEventListenerSpy.firstCall, 'focusin'); assert.calledWith(removeEventListenerSpy.secondCall, 'focusout'); assert.calledWith(removeEventListenerSpy.thirdCall, 'keydown'); }); }); });