diff options
Diffstat (limited to 'spec/frontend/sidebar/sidebar_move_issue_spec.js')
-rw-r--r-- | spec/frontend/sidebar/sidebar_move_issue_spec.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js new file mode 100644 index 00000000000..db0d3e06272 --- /dev/null +++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js @@ -0,0 +1,167 @@ +import $ from 'jquery'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import SidebarMediator from '~/sidebar/sidebar_mediator'; +import SidebarStore from '~/sidebar/stores/sidebar_store'; +import SidebarService from '~/sidebar/services/sidebar_service'; +import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue'; +import Mock from './mock_data'; + +describe('SidebarMoveIssue', () => { + let mock; + const test = {}; + + beforeEach(() => { + mock = new MockAdapter(axios); + const mockData = Mock.responseMap.GET['/autocomplete/projects?project_id=15']; + mock.onGet('/autocomplete/projects?project_id=15').reply(200, mockData); + test.mediator = new SidebarMediator(Mock.mediator); + test.$content = $(` + <div class="dropdown"> + <div class="js-toggle"></div> + <div class="dropdown-menu"> + <div class="dropdown-content"></div> + </div> + <div class="js-confirm-button"></div> + </div> + `); + test.$toggleButton = test.$content.find('.js-toggle'); + test.$confirmButton = test.$content.find('.js-confirm-button'); + + test.sidebarMoveIssue = new SidebarMoveIssue( + test.mediator, + test.$toggleButton, + test.$confirmButton, + ); + test.sidebarMoveIssue.init(); + }); + + afterEach(() => { + SidebarService.singleton = null; + SidebarStore.singleton = null; + SidebarMediator.singleton = null; + + test.sidebarMoveIssue.destroy(); + mock.restore(); + }); + + describe('init', () => { + it('should initialize the dropdown and listeners', () => { + jest.spyOn(test.sidebarMoveIssue, 'initDropdown').mockImplementation(() => {}); + jest.spyOn(test.sidebarMoveIssue, 'addEventListeners').mockImplementation(() => {}); + + test.sidebarMoveIssue.init(); + + expect(test.sidebarMoveIssue.initDropdown).toHaveBeenCalled(); + expect(test.sidebarMoveIssue.addEventListeners).toHaveBeenCalled(); + }); + }); + + describe('destroy', () => { + it('should remove the listeners', () => { + jest.spyOn(test.sidebarMoveIssue, 'removeEventListeners').mockImplementation(() => {}); + + test.sidebarMoveIssue.destroy(); + + expect(test.sidebarMoveIssue.removeEventListeners).toHaveBeenCalled(); + }); + }); + + describe('initDropdown', () => { + it('should initialize the gl_dropdown', () => { + jest.spyOn($.fn, 'glDropdown').mockImplementation(() => {}); + + test.sidebarMoveIssue.initDropdown(); + + expect($.fn.glDropdown).toHaveBeenCalled(); + }); + + it('escapes html from project name', done => { + test.$toggleButton.dropdown('toggle'); + + setImmediate(() => { + expect(test.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual( + '<img src=x onerror=alert(document.domain)> foo / bar', + ); + done(); + }); + }); + }); + + describe('onConfirmClicked', () => { + it('should move the issue with valid project ID', () => { + jest.spyOn(test.mediator, 'moveIssue').mockReturnValue(Promise.resolve()); + test.mediator.setMoveToProjectId(7); + + test.sidebarMoveIssue.onConfirmClicked(); + + expect(test.mediator.moveIssue).toHaveBeenCalled(); + expect(test.$confirmButton.prop('disabled')).toBeTruthy(); + expect(test.$confirmButton.hasClass('is-loading')).toBe(true); + }); + + it('should remove loading state from confirm button on failure', done => { + jest.spyOn(window, 'Flash').mockImplementation(() => {}); + jest.spyOn(test.mediator, 'moveIssue').mockReturnValue(Promise.reject()); + test.mediator.setMoveToProjectId(7); + + test.sidebarMoveIssue.onConfirmClicked(); + + expect(test.mediator.moveIssue).toHaveBeenCalled(); + // Wait for the move issue request to fail + setImmediate(() => { + expect(window.Flash).toHaveBeenCalled(); + expect(test.$confirmButton.prop('disabled')).toBeFalsy(); + expect(test.$confirmButton.hasClass('is-loading')).toBe(false); + done(); + }); + }); + + it('should not move the issue with id=0', () => { + jest.spyOn(test.mediator, 'moveIssue').mockImplementation(() => {}); + test.mediator.setMoveToProjectId(0); + + test.sidebarMoveIssue.onConfirmClicked(); + + expect(test.mediator.moveIssue).not.toHaveBeenCalled(); + }); + }); + + it('should set moveToProjectId on dropdown item "No project" click', done => { + jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {}); + + // Open the dropdown + test.$toggleButton.dropdown('toggle'); + + // Wait for the autocomplete request to finish + setImmediate(() => { + test.$content + .find('.js-move-issue-dropdown-item') + .eq(0) + .trigger('click'); + + expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(0); + expect(test.$confirmButton.prop('disabled')).toBeTruthy(); + done(); + }); + }); + + it('should set moveToProjectId on dropdown item click', done => { + jest.spyOn(test.mediator, 'setMoveToProjectId').mockImplementation(() => {}); + + // Open the dropdown + test.$toggleButton.dropdown('toggle'); + + // Wait for the autocomplete request to finish + setImmediate(() => { + test.$content + .find('.js-move-issue-dropdown-item') + .eq(1) + .trigger('click'); + + expect(test.mediator.setMoveToProjectId).toHaveBeenCalledWith(20); + expect(test.$confirmButton.attr('disabled')).toBe(undefined); + done(); + }); + }); +}); |