diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/file_finder/index_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/file_finder/index_spec.js | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/file_finder/index_spec.js b/spec/frontend/vue_shared/components/file_finder/index_spec.js new file mode 100644 index 00000000000..f9e56774526 --- /dev/null +++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js @@ -0,0 +1,368 @@ +import Vue from 'vue'; +import Mousetrap from 'mousetrap'; +import { file } from 'jest/ide/helpers'; +import waitForPromises from 'helpers/wait_for_promises'; +import FindFileComponent from '~/vue_shared/components/file_finder/index.vue'; +import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes'; + +describe('File finder item spec', () => { + const Component = Vue.extend(FindFileComponent); + let vm; + + function createComponent(props) { + vm = new Component({ + propsData: { + files: [], + visible: true, + loading: false, + ...props, + }, + }); + + vm.$mount('#app'); + } + + beforeEach(() => { + setFixtures('<div id="app"></div>'); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('with entries', () => { + beforeEach(done => { + createComponent({ + files: [ + { + ...file('index.js'), + path: 'index.js', + type: 'blob', + url: '/index.jsurl', + }, + { + ...file('component.js'), + path: 'component.js', + type: 'blob', + }, + ], + }); + + setImmediate(done); + }); + + it('renders list of blobs', () => { + expect(vm.$el.textContent).toContain('index.js'); + expect(vm.$el.textContent).toContain('component.js'); + expect(vm.$el.textContent).not.toContain('folder'); + }); + + it('filters entries', done => { + vm.searchText = 'index'; + + setImmediate(() => { + expect(vm.$el.textContent).toContain('index.js'); + expect(vm.$el.textContent).not.toContain('component.js'); + + done(); + }); + }); + + it('shows clear button when searchText is not empty', done => { + vm.searchText = 'index'; + + setImmediate(() => { + expect(vm.$el.querySelector('.dropdown-input').classList).toContain('has-value'); + expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden'); + + done(); + }); + }); + + it('clear button resets searchText', done => { + vm.searchText = 'index'; + + waitForPromises() + .then(() => { + vm.$el.querySelector('.dropdown-input-clear').click(); + }) + .then(waitForPromises) + .then(() => { + expect(vm.searchText).toBe(''); + }) + .then(done) + .catch(done.fail); + }); + + it('clear button focues search input', done => { + jest.spyOn(vm.$refs.searchInput, 'focus').mockImplementation(() => {}); + vm.searchText = 'index'; + + waitForPromises() + .then(() => { + vm.$el.querySelector('.dropdown-input-clear').click(); + }) + .then(waitForPromises) + .then(() => { + expect(vm.$refs.searchInput.focus).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + describe('listShowCount', () => { + it('returns 1 when no filtered entries exist', done => { + vm.searchText = 'testing 123'; + + setImmediate(() => { + expect(vm.listShowCount).toBe(1); + + done(); + }); + }); + + it('returns entries length when not filtered', () => { + expect(vm.listShowCount).toBe(2); + }); + }); + + describe('listHeight', () => { + it('returns 55 when entries exist', () => { + expect(vm.listHeight).toBe(55); + }); + + it('returns 33 when entries dont exist', done => { + vm.searchText = 'testing 123'; + + setImmediate(() => { + expect(vm.listHeight).toBe(33); + + done(); + }); + }); + }); + + describe('filteredBlobsLength', () => { + it('returns length of filtered blobs', done => { + vm.searchText = 'index'; + + setImmediate(() => { + expect(vm.filteredBlobsLength).toBe(1); + + done(); + }); + }); + }); + + describe('watches', () => { + describe('searchText', () => { + it('resets focusedIndex when updated', done => { + vm.focusedIndex = 1; + vm.searchText = 'test'; + + setImmediate(() => { + expect(vm.focusedIndex).toBe(0); + + done(); + }); + }); + }); + + describe('visible', () => { + it('returns searchText when false', done => { + vm.searchText = 'test'; + vm.visible = true; + + waitForPromises() + .then(() => { + vm.visible = false; + }) + .then(waitForPromises) + .then(() => { + expect(vm.searchText).toBe(''); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + + describe('openFile', () => { + beforeEach(() => { + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + }); + + it('closes file finder', () => { + vm.openFile(vm.files[0]); + + expect(vm.$emit).toHaveBeenCalledWith('toggle', false); + }); + + it('pushes to router', () => { + vm.openFile(vm.files[0]); + + expect(vm.$emit).toHaveBeenCalledWith('click', vm.files[0]); + }); + }); + + describe('onKeyup', () => { + it('opens file on enter key', done => { + const event = new CustomEvent('keyup'); + event.keyCode = ENTER_KEY_CODE; + + jest.spyOn(vm, 'openFile').mockImplementation(() => {}); + + vm.$refs.searchInput.dispatchEvent(event); + + setImmediate(() => { + expect(vm.openFile).toHaveBeenCalledWith(vm.files[0]); + + done(); + }); + }); + + it('closes file finder on esc key', done => { + const event = new CustomEvent('keyup'); + event.keyCode = ESC_KEY_CODE; + + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + + vm.$refs.searchInput.dispatchEvent(event); + + setImmediate(() => { + expect(vm.$emit).toHaveBeenCalledWith('toggle', false); + + done(); + }); + }); + }); + + describe('onKeyDown', () => { + let el; + + beforeEach(() => { + el = vm.$refs.searchInput; + }); + + describe('up key', () => { + const event = new CustomEvent('keydown'); + event.keyCode = UP_KEY_CODE; + + it('resets to last index when at top', () => { + el.dispatchEvent(event); + + expect(vm.focusedIndex).toBe(1); + }); + + it('minus 1 from focusedIndex', () => { + vm.focusedIndex = 1; + + el.dispatchEvent(event); + + expect(vm.focusedIndex).toBe(0); + }); + }); + + describe('down key', () => { + const event = new CustomEvent('keydown'); + event.keyCode = DOWN_KEY_CODE; + + it('resets to first index when at bottom', () => { + vm.focusedIndex = 1; + el.dispatchEvent(event); + + expect(vm.focusedIndex).toBe(0); + }); + + it('adds 1 to focusedIndex', () => { + el.dispatchEvent(event); + + expect(vm.focusedIndex).toBe(1); + }); + }); + }); + }); + + describe('without entries', () => { + it('renders loading text when loading', () => { + createComponent({ + loading: true, + }); + + expect(vm.$el.textContent).toContain('Loading...'); + }); + + it('renders no files text', () => { + createComponent(); + + expect(vm.$el.textContent).toContain('No files found.'); + }); + }); + + describe('keyboard shortcuts', () => { + beforeEach(done => { + createComponent(); + + jest.spyOn(vm, 'toggle').mockImplementation(() => {}); + + vm.$nextTick(done); + }); + + it('calls toggle on `t` key press', done => { + Mousetrap.trigger('t'); + + vm.$nextTick() + .then(() => { + expect(vm.toggle).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('calls toggle on `command+p` key press', done => { + Mousetrap.trigger('command+p'); + + vm.$nextTick() + .then(() => { + expect(vm.toggle).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('calls toggle on `ctrl+p` key press', done => { + Mousetrap.trigger('ctrl+p'); + + vm.$nextTick() + .then(() => { + expect(vm.toggle).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('always allows `command+p` to trigger toggle', () => { + expect( + vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'command+p'), + ).toBe(false); + }); + + it('always allows `ctrl+p` to trigger toggle', () => { + expect( + vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'ctrl+p'), + ).toBe(false); + }); + + it('onlys handles `t` when focused in input-field', () => { + expect( + vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 't'), + ).toBe(true); + }); + + it('stops callback in monaco editor', () => { + setFixtures('<div class="inputarea"></div>'); + + expect(vm.mousetrapStopCallback(null, document.querySelector('.inputarea'), 't')).toBe(true); + }); + }); +}); |