diff options
Diffstat (limited to 'spec/frontend/vue_shared/directives')
-rw-r--r-- | spec/frontend/vue_shared/directives/autofocusonshow_spec.js | 46 | ||||
-rw-r--r-- | spec/frontend/vue_shared/directives/tooltip_spec.js | 98 |
2 files changed, 144 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/directives/autofocusonshow_spec.js b/spec/frontend/vue_shared/directives/autofocusonshow_spec.js new file mode 100644 index 00000000000..90530b7d5c2 --- /dev/null +++ b/spec/frontend/vue_shared/directives/autofocusonshow_spec.js @@ -0,0 +1,46 @@ +import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; + +/** + * We're testing this directive's hooks as pure functions + * since behaviour of this directive is highly-dependent + * on underlying DOM methods. + */ +describe('AutofocusOnShow directive', () => { + describe('with input invisible on component render', () => { + let el; + + beforeEach(() => { + setFixtures('<div id="container" style="display: none;"><input id="inputel"/></div>'); + el = document.querySelector('#inputel'); + + window.IntersectionObserver = class { + observe = jest.fn(); + }; + }); + + afterEach(() => { + delete window.IntersectionObserver; + }); + + it('should bind IntersectionObserver on input element', () => { + jest.spyOn(el, 'focus').mockImplementation(() => {}); + + autofocusonshow.inserted(el); + + expect(el.visibilityObserver).toBeDefined(); + expect(el.focus).not.toHaveBeenCalled(); + }); + + it('should stop IntersectionObserver on input element on unbind hook', () => { + el.visibilityObserver = { + disconnect: () => {}, + }; + jest.spyOn(el.visibilityObserver, 'disconnect').mockImplementation(() => {}); + + autofocusonshow.unbind(el); + + expect(el.visibilityObserver).toBeDefined(); + expect(el.visibilityObserver.disconnect).toHaveBeenCalled(); + }); + }); +}); diff --git a/spec/frontend/vue_shared/directives/tooltip_spec.js b/spec/frontend/vue_shared/directives/tooltip_spec.js new file mode 100644 index 00000000000..9d3dd3c5f75 --- /dev/null +++ b/spec/frontend/vue_shared/directives/tooltip_spec.js @@ -0,0 +1,98 @@ +import $ from 'jquery'; +import { mount } from '@vue/test-utils'; +import tooltip from '~/vue_shared/directives/tooltip'; + +describe('Tooltip directive', () => { + let vm; + + afterEach(() => { + if (vm) { + vm.$destroy(); + } + }); + + describe('with a single tooltip', () => { + beforeEach(() => { + const wrapper = mount( + { + directives: { + tooltip, + }, + data() { + return { + tooltip: 'some text', + }; + }, + template: '<div v-tooltip :title="tooltip"></div>', + }, + { attachToDocument: true }, + ); + + vm = wrapper.vm; + }); + + it('should have tooltip plugin applied', () => { + expect($(vm.$el).data('bs.tooltip')).toBeDefined(); + }); + + it('displays the title as tooltip', () => { + $(vm.$el).tooltip('show'); + jest.runOnlyPendingTimers(); + + const tooltipElement = document.querySelector('.tooltip-inner'); + + expect(tooltipElement.textContent).toContain('some text'); + }); + + it('updates a visible tooltip', () => { + $(vm.$el).tooltip('show'); + jest.runOnlyPendingTimers(); + + const tooltipElement = document.querySelector('.tooltip-inner'); + + vm.tooltip = 'other text'; + + jest.runOnlyPendingTimers(); + + return vm.$nextTick().then(() => { + expect(tooltipElement.textContent).toContain('other text'); + }); + }); + }); + + describe('with multiple tooltips', () => { + beforeEach(() => { + const wrapper = mount( + { + directives: { + tooltip, + }, + template: ` + <div> + <div + v-tooltip + class="js-look-for-tooltip" + title="foo"> + </div> + <div + v-tooltip + title="bar"> + </div> + </div> + `, + }, + { attachToDocument: true }, + ); + + vm = wrapper.vm; + }); + + it('should have tooltip plugin applied to all instances', () => { + expect( + $(vm.$el) + .find('.js-look-for-tooltip') + .data('bs.tooltip'), + ).toBeDefined(); + }); + }); +}); |