diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-08 09:08:23 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-08 09:08:23 +0000 |
commit | b001207ce2033589373cd7558ca69c4e5732ce6b (patch) | |
tree | 11f0b257a3a8e4644afd8995ac628a869d6d3811 /spec/javascripts | |
parent | 449287e15a3633f7a17533c2da0273e31ddf1c1f (diff) | |
download | gitlab-ce-b001207ce2033589373cd7558ca69c4e5732ce6b.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/javascripts')
-rw-r--r-- | spec/javascripts/awards_handler_spec.js | 400 | ||||
-rw-r--r-- | spec/javascripts/collapsed_sidebar_todo_spec.js | 171 | ||||
-rw-r--r-- | spec/javascripts/comment_type_toggle_spec.js | 168 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js | 126 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js | 722 | ||||
-rw-r--r-- | spec/javascripts/gl_form_spec.js | 110 | ||||
-rw-r--r-- | spec/javascripts/global_search_input_spec.js | 215 | ||||
-rw-r--r-- | spec/javascripts/labels_issue_sidebar_spec.js | 97 | ||||
-rw-r--r-- | spec/javascripts/line_highlighter_spec.js | 261 | ||||
-rw-r--r-- | spec/javascripts/merge_request_tabs_spec.js | 294 | ||||
-rw-r--r-- | spec/javascripts/right_sidebar_spec.js | 87 | ||||
-rw-r--r-- | spec/javascripts/shortcuts_spec.js | 46 | ||||
-rw-r--r-- | spec/javascripts/user_popovers_spec.js | 95 | ||||
-rw-r--r-- | spec/javascripts/zen_mode_spec.js | 106 |
14 files changed, 0 insertions, 2898 deletions
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js deleted file mode 100644 index 02200f77ad7..00000000000 --- a/spec/javascripts/awards_handler_spec.js +++ /dev/null @@ -1,400 +0,0 @@ -import $ from 'jquery'; -import Cookies from 'js-cookie'; -import loadAwardsHandler from '~/awards_handler'; -import '~/lib/utils/common_utils'; - -window.gl = window.gl || {}; -window.gon = window.gon || {}; - -let openAndWaitForEmojiMenu; -let awardsHandler = null; -const urlRoot = gon.relative_url_root; - -const lazyAssert = function(done, assertFn) { - setTimeout(function() { - assertFn(); - done(); - // Maybe jasmine.clock here? - }, 333); -}; - -describe('AwardsHandler', function() { - preloadFixtures('snippets/show.html'); - beforeEach(function(done) { - loadFixtures('snippets/show.html'); - loadAwardsHandler(true) - .then(obj => { - awardsHandler = obj; - spyOn(awardsHandler, 'postEmoji').and.callFake((button, url, emoji, cb) => cb()); - done(); - }) - .catch(fail); - - let isEmojiMenuBuilt = false; - openAndWaitForEmojiMenu = function() { - return new Promise(resolve => { - if (isEmojiMenuBuilt) { - resolve(); - } else { - $('.js-add-award') - .eq(0) - .click(); - const $menu = $('.emoji-menu'); - $menu.one('build-emoji-menu-finish', () => { - isEmojiMenuBuilt = true; - resolve(); - }); - } - }); - }; - }); - - afterEach(function() { - // restore original url root value - gon.relative_url_root = urlRoot; - - // Undo what we did to the shared <body> - $('body').removeAttr('data-page'); - - awardsHandler.destroy(); - }); - - describe('::showEmojiMenu', function() { - it('should show emoji menu when Add emoji button clicked', function(done) { - $('.js-add-award') - .eq(0) - .click(); - lazyAssert(done, function() { - const $emojiMenu = $('.emoji-menu'); - - expect($emojiMenu.length).toBe(1); - expect($emojiMenu.hasClass('is-visible')).toBe(true); - expect($emojiMenu.find('.js-emoji-menu-search').length).toBe(1); - expect($('.js-awards-block.current').length).toBe(1); - }); - }); - - it('should also show emoji menu for the smiley icon in notes', function(done) { - $('.js-add-award.note-action-button').click(); - lazyAssert(done, function() { - const $emojiMenu = $('.emoji-menu'); - - expect($emojiMenu.length).toBe(1); - }); - }); - - it('should remove emoji menu when body is clicked', function(done) { - $('.js-add-award') - .eq(0) - .click(); - lazyAssert(done, function() { - const $emojiMenu = $('.emoji-menu'); - $('body').click(); - - expect($emojiMenu.length).toBe(1); - expect($emojiMenu.hasClass('is-visible')).toBe(false); - expect($('.js-awards-block.current').length).toBe(0); - }); - }); - - it('should not remove emoji menu when search is clicked', function(done) { - $('.js-add-award') - .eq(0) - .click(); - lazyAssert(done, function() { - const $emojiMenu = $('.emoji-menu'); - $('.emoji-search').click(); - - expect($emojiMenu.length).toBe(1); - expect($emojiMenu.hasClass('is-visible')).toBe(true); - expect($('.js-awards-block.current').length).toBe(1); - }); - }); - }); - - describe('::addAwardToEmojiBar', function() { - it('should add emoji to votes block', function() { - const $votesBlock = $('.js-awards-block').eq(0); - awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false); - const $emojiButton = $votesBlock.find('[data-name=heart]'); - - expect($emojiButton.length).toBe(1); - expect($emojiButton.next('.js-counter').text()).toBe('1'); - expect($votesBlock.hasClass('hidden')).toBe(false); - }); - - it('should remove the emoji when we click again', function() { - const $votesBlock = $('.js-awards-block').eq(0); - awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false); - awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false); - const $emojiButton = $votesBlock.find('[data-name=heart]'); - - expect($emojiButton.length).toBe(0); - }); - - it('should decrement the emoji counter', function() { - const $votesBlock = $('.js-awards-block').eq(0); - awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false); - const $emojiButton = $votesBlock.find('[data-name=heart]'); - $emojiButton.next('.js-counter').text(5); - awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false); - - expect($emojiButton.length).toBe(1); - expect($emojiButton.next('.js-counter').text()).toBe('4'); - }); - }); - - describe('::userAuthored', function() { - it('should update tooltip to user authored title', function() { - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'sam'); - awardsHandler.userAuthored($thumbsUpEmoji); - - expect($thumbsUpEmoji.data('originalTitle')).toBe( - 'You cannot vote on your own issue, MR and note', - ); - }); - - it('should restore tooltip back to initial vote list', function() { - jasmine.clock().install(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'sam'); - awardsHandler.userAuthored($thumbsUpEmoji); - jasmine.clock().tick(2801); - jasmine.clock().uninstall(); - - expect($thumbsUpEmoji.data('originalTitle')).toBe('sam'); - }); - }); - - describe('::getAwardUrl', function() { - it('returns the url for request', function() { - expect(awardsHandler.getAwardUrl()).toBe('http://test.host/snippets/1/toggle_award_emoji'); - }); - }); - - describe('::addAward and ::checkMutuality', function() { - it('should handle :+1: and :-1: mutuality', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - const $thumbsDownEmoji = $votesBlock.find('[data-name=thumbsdown]').parent(); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); - - expect($thumbsUpEmoji.hasClass('active')).toBe(true); - expect($thumbsDownEmoji.hasClass('active')).toBe(false); - $thumbsUpEmoji.tooltip(); - $thumbsDownEmoji.tooltip(); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsdown', true); - - expect($thumbsUpEmoji.hasClass('active')).toBe(false); - expect($thumbsDownEmoji.hasClass('active')).toBe(true); - }); - }); - - describe('::removeEmoji', function() { - it('should remove emoji', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - awardsHandler.addAward($votesBlock, awardUrl, 'fire', false); - - expect($votesBlock.find('[data-name=fire]').length).toBe(1); - awardsHandler.removeEmoji($votesBlock.find('[data-name=fire]').closest('button')); - - expect($votesBlock.find('[data-name=fire]').length).toBe(0); - }); - }); - - describe('::addYouToUserList', function() { - it('should prepend "You" to the award tooltip', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'sam, jerry, max, and andy'); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); - $thumbsUpEmoji.tooltip(); - - expect($thumbsUpEmoji.data('originalTitle')).toBe('You, sam, jerry, max, and andy'); - }); - - it('handles the special case where "You" is not cleanly comma separated', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'sam'); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); - $thumbsUpEmoji.tooltip(); - - expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam'); - }); - }); - - describe('::removeYouToUserList', function() { - it('removes "You" from the front of the tooltip', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'You, sam, jerry, max, and andy'); - $thumbsUpEmoji.addClass('active'); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); - $thumbsUpEmoji.tooltip(); - - expect($thumbsUpEmoji.data('originalTitle')).toBe('sam, jerry, max, and andy'); - }); - - it('handles the special case where "You" is not cleanly comma separated', function() { - const awardUrl = awardsHandler.getAwardUrl(); - const $votesBlock = $('.js-awards-block').eq(0); - const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent(); - $thumbsUpEmoji.attr('data-title', 'You and sam'); - $thumbsUpEmoji.addClass('active'); - awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); - $thumbsUpEmoji.tooltip(); - - expect($thumbsUpEmoji.data('originalTitle')).toBe('sam'); - }); - }); - - describe('::searchEmojis', () => { - it('should filter the emoji', function(done) { - openAndWaitForEmojiMenu() - .then(() => { - expect($('[data-name=angel]').is(':visible')).toBe(true); - expect($('[data-name=anger]').is(':visible')).toBe(true); - awardsHandler.searchEmojis('ali'); - - expect($('[data-name=angel]').is(':visible')).toBe(false); - expect($('[data-name=anger]').is(':visible')).toBe(false); - expect($('[data-name=alien]').is(':visible')).toBe(true); - expect($('.js-emoji-menu-search').val()).toBe('ali'); - }) - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - - it('should clear the search when searching for nothing', function(done) { - openAndWaitForEmojiMenu() - .then(() => { - awardsHandler.searchEmojis('ali'); - - expect($('[data-name=angel]').is(':visible')).toBe(false); - expect($('[data-name=anger]').is(':visible')).toBe(false); - expect($('[data-name=alien]').is(':visible')).toBe(true); - awardsHandler.searchEmojis(''); - - expect($('[data-name=angel]').is(':visible')).toBe(true); - expect($('[data-name=anger]').is(':visible')).toBe(true); - expect($('[data-name=alien]').is(':visible')).toBe(true); - expect($('.js-emoji-menu-search').val()).toBe(''); - }) - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - }); - - describe('emoji menu', function() { - const emojiSelector = '[data-name="sunglasses"]'; - const openEmojiMenuAndAddEmoji = function() { - return openAndWaitForEmojiMenu().then(() => { - const $menu = $('.emoji-menu'); - const $block = $('.js-awards-block'); - const $emoji = $menu.find(`.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`); - - expect($emoji.length).toBe(1); - expect($block.find(emojiSelector).length).toBe(0); - $emoji.click(); - - expect($menu.hasClass('.is-visible')).toBe(false); - expect($block.find(emojiSelector).length).toBe(1); - }); - }; - - it('should add selected emoji to awards block', function(done) { - openEmojiMenuAndAddEmoji() - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - - it('should remove already selected emoji', function(done) { - openEmojiMenuAndAddEmoji() - .then(() => { - $('.js-add-award') - .eq(0) - .click(); - const $block = $('.js-awards-block'); - const $emoji = $('.emoji-menu').find( - `.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`, - ); - $emoji.click(); - - expect($block.find(emojiSelector).length).toBe(0); - }) - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - }); - - describe('frequently used emojis', function() { - beforeEach(() => { - // Clear it out - Cookies.set('frequently_used_emojis', ''); - }); - - it('shouldn\'t have any "Frequently used" heading if no frequently used emojis', function(done) { - return openAndWaitForEmojiMenu() - .then(() => { - const emojiMenu = document.querySelector('.emoji-menu'); - Array.prototype.forEach.call(emojiMenu.querySelectorAll('.emoji-menu-title'), title => { - expect(title.textContent.trim().toLowerCase()).not.toBe('frequently used'); - }); - }) - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - - it('should have any frequently used section when there are frequently used emojis', function(done) { - awardsHandler.addEmojiToFrequentlyUsedList('8ball'); - - return openAndWaitForEmojiMenu() - .then(() => { - const emojiMenu = document.querySelector('.emoji-menu'); - const hasFrequentlyUsedHeading = Array.prototype.some.call( - emojiMenu.querySelectorAll('.emoji-menu-title'), - title => title.textContent.trim().toLowerCase() === 'frequently used', - ); - - expect(hasFrequentlyUsedHeading).toBe(true); - }) - .then(done) - .catch(err => { - done.fail(`Failed to open and build emoji menu: ${err.message}`); - }); - }); - - it('should disregard invalid frequently used emoji that are being attempted to be added', function() { - awardsHandler.addEmojiToFrequentlyUsedList('8ball'); - awardsHandler.addEmojiToFrequentlyUsedList('invalid_emoji'); - awardsHandler.addEmojiToFrequentlyUsedList('grinning'); - - expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']); - }); - - it('should disregard invalid frequently used emoji already set in cookie', function() { - Cookies.set('frequently_used_emojis', '8ball,invalid_emoji,grinning'); - - expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']); - }); - }); -}); diff --git a/spec/javascripts/collapsed_sidebar_todo_spec.js b/spec/javascripts/collapsed_sidebar_todo_spec.js deleted file mode 100644 index f2eb08fa198..00000000000 --- a/spec/javascripts/collapsed_sidebar_todo_spec.js +++ /dev/null @@ -1,171 +0,0 @@ -/* eslint-disable no-new */ -import { clone } from 'lodash'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import Sidebar from '~/right_sidebar'; -import timeoutPromise from './helpers/set_timeout_promise_helper'; - -describe('Issuable right sidebar collapsed todo toggle', () => { - const fixtureName = 'issues/open-issue.html'; - const jsonFixtureName = 'todos/todos.json'; - let mock; - - preloadFixtures(fixtureName); - preloadFixtures(jsonFixtureName); - - beforeEach(() => { - const todoData = getJSONFixture(jsonFixtureName); - new Sidebar(); - loadFixtures(fixtureName); - - document.querySelector('.js-right-sidebar').classList.toggle('right-sidebar-expanded'); - document.querySelector('.js-right-sidebar').classList.toggle('right-sidebar-collapsed'); - - mock = new MockAdapter(axios); - - mock.onPost(`${gl.TEST_HOST}/frontend-fixtures/issues-project/todos`).reply(() => { - const response = clone(todoData); - - return [200, response]; - }); - - mock.onDelete(/(.*)\/dashboard\/todos\/\d+$/).reply(() => { - const response = clone(todoData); - delete response.delete_path; - - return [200, response]; - }); - }); - - afterEach(() => { - mock.restore(); - }); - - it('shows add todo button', () => { - expect(document.querySelector('.js-issuable-todo.sidebar-collapsed-icon')).not.toBeNull(); - - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg use') - .getAttribute('xlink:href'), - ).toContain('todo-add'); - - expect( - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'), - ).toBeNull(); - }); - - it('sets default tooltip title', () => { - expect( - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').getAttribute('title'), - ).toBe('Add a To Do'); - }); - - it('toggle todo state', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - setTimeout(() => { - expect( - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'), - ).not.toBeNull(); - - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone use') - .getAttribute('xlink:href'), - ).toContain('todo-done'); - - done(); - }); - }); - - it('toggle todo state of expanded todo toggle', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - setTimeout(() => { - expect( - document.querySelector('.issuable-sidebar-header .js-issuable-todo').textContent.trim(), - ).toBe('Mark as done'); - - done(); - }); - }); - - it('toggles todo button tooltip', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - setTimeout(() => { - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon') - .getAttribute('data-original-title'), - ).toBe('Mark as done'); - - done(); - }); - }); - - it('marks todo as done', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - timeoutPromise() - .then(() => { - expect( - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'), - ).not.toBeNull(); - - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - }) - .then(timeoutPromise) - .then(() => { - expect( - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'), - ).toBeNull(); - - expect( - document.querySelector('.issuable-sidebar-header .js-issuable-todo').textContent.trim(), - ).toBe('Add a To Do'); - }) - .then(done) - .catch(done.fail); - }); - - it('updates aria-label to Mark as done', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - setTimeout(() => { - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon') - .getAttribute('aria-label'), - ).toBe('Mark as done'); - - done(); - }); - }); - - it('updates aria-label to add todo', done => { - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - - timeoutPromise() - .then(() => { - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon') - .getAttribute('aria-label'), - ).toBe('Mark as done'); - - document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click(); - }) - .then(timeoutPromise) - .then(() => { - expect( - document - .querySelector('.js-issuable-todo.sidebar-collapsed-icon') - .getAttribute('aria-label'), - ).toBe('Add a To Do'); - }) - .then(done) - .catch(done.fail); - }); -}); diff --git a/spec/javascripts/comment_type_toggle_spec.js b/spec/javascripts/comment_type_toggle_spec.js deleted file mode 100644 index 8b1217a000f..00000000000 --- a/spec/javascripts/comment_type_toggle_spec.js +++ /dev/null @@ -1,168 +0,0 @@ -import CommentTypeToggle from '~/comment_type_toggle'; -import InputSetter from '~/droplab/plugins/input_setter'; - -describe('CommentTypeToggle', function() { - describe('class constructor', function() { - beforeEach(function() { - this.dropdownTrigger = {}; - this.dropdownList = {}; - this.noteTypeInput = {}; - this.submitButton = {}; - this.closeButton = {}; - - this.commentTypeToggle = new CommentTypeToggle({ - dropdownTrigger: this.dropdownTrigger, - dropdownList: this.dropdownList, - noteTypeInput: this.noteTypeInput, - submitButton: this.submitButton, - closeButton: this.closeButton, - }); - }); - - it('should set .dropdownTrigger', function() { - expect(this.commentTypeToggle.dropdownTrigger).toBe(this.dropdownTrigger); - }); - - it('should set .dropdownList', function() { - expect(this.commentTypeToggle.dropdownList).toBe(this.dropdownList); - }); - - it('should set .noteTypeInput', function() { - expect(this.commentTypeToggle.noteTypeInput).toBe(this.noteTypeInput); - }); - - it('should set .submitButton', function() { - expect(this.commentTypeToggle.submitButton).toBe(this.submitButton); - }); - - it('should set .closeButton', function() { - expect(this.commentTypeToggle.closeButton).toBe(this.closeButton); - }); - - it('should set .reopenButton', function() { - expect(this.commentTypeToggle.reopenButton).toBe(this.reopenButton); - }); - }); - - describe('initDroplab', function() { - beforeEach(function() { - this.commentTypeToggle = { - dropdownTrigger: {}, - dropdownList: {}, - noteTypeInput: {}, - submitButton: {}, - closeButton: {}, - setConfig: () => {}, - }; - this.config = {}; - - this.droplab = jasmine.createSpyObj('droplab', ['init']); - - this.droplabConstructor = spyOnDependency(CommentTypeToggle, 'DropLab').and.returnValue( - this.droplab, - ); - spyOn(this.commentTypeToggle, 'setConfig').and.returnValue(this.config); - - CommentTypeToggle.prototype.initDroplab.call(this.commentTypeToggle); - }); - - it('should instantiate a DropLab instance', function() { - expect(this.droplabConstructor).toHaveBeenCalled(); - }); - - it('should set .droplab', function() { - expect(this.commentTypeToggle.droplab).toBe(this.droplab); - }); - - it('should call .setConfig', function() { - expect(this.commentTypeToggle.setConfig).toHaveBeenCalled(); - }); - - it('should call DropLab.prototype.init', function() { - expect(this.droplab.init).toHaveBeenCalledWith( - this.commentTypeToggle.dropdownTrigger, - this.commentTypeToggle.dropdownList, - [InputSetter], - this.config, - ); - }); - }); - - describe('setConfig', function() { - describe('if no .closeButton is provided', function() { - beforeEach(function() { - this.commentTypeToggle = { - dropdownTrigger: {}, - dropdownList: {}, - noteTypeInput: {}, - submitButton: {}, - reopenButton: {}, - }; - - this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle); - }); - - it('should not add .closeButton related InputSetter config', function() { - expect(this.setConfig).toEqual({ - InputSetter: [ - { - input: this.commentTypeToggle.noteTypeInput, - valueAttribute: 'data-value', - }, - { - input: this.commentTypeToggle.submitButton, - valueAttribute: 'data-submit-text', - }, - { - input: this.commentTypeToggle.reopenButton, - valueAttribute: 'data-reopen-text', - }, - { - input: this.commentTypeToggle.reopenButton, - valueAttribute: 'data-reopen-text', - inputAttribute: 'data-alternative-text', - }, - ], - }); - }); - }); - - describe('if no .reopenButton is provided', function() { - beforeEach(function() { - this.commentTypeToggle = { - dropdownTrigger: {}, - dropdownList: {}, - noteTypeInput: {}, - submitButton: {}, - closeButton: {}, - }; - - this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle); - }); - - it('should not add .reopenButton related InputSetter config', function() { - expect(this.setConfig).toEqual({ - InputSetter: [ - { - input: this.commentTypeToggle.noteTypeInput, - valueAttribute: 'data-value', - }, - { - input: this.commentTypeToggle.submitButton, - valueAttribute: 'data-submit-text', - }, - { - input: this.commentTypeToggle.closeButton, - valueAttribute: 'data-close-text', - }, - { - input: this.commentTypeToggle.closeButton, - valueAttribute: 'data-close-text', - inputAttribute: 'data-alternative-text', - }, - ], - }); - }); - }); - }); -}); diff --git a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js deleted file mode 100644 index 853f6b3b7b8..00000000000 --- a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js +++ /dev/null @@ -1,126 +0,0 @@ -import $ from 'jquery'; -import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager'; - -describe('Filtered Search Dropdown Manager', () => { - beforeEach(() => { - spyOn($, 'ajax'); - }); - - describe('addWordToInput', () => { - function getInputValue() { - return document.querySelector('.filtered-search').value; - } - - function setInputValue(value) { - document.querySelector('.filtered-search').value = value; - } - - beforeEach(() => { - setFixtures(` - <ul class="tokens-container"> - <li class="input-token"> - <input class="filtered-search"> - </li> - </ul> - `); - }); - - describe('input has no existing value', () => { - it('should add just tokenName', () => { - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'milestone' }); - - const token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('milestone'); - expect(getInputValue()).toBe(''); - }); - - it('should add tokenName, tokenOperator, and tokenValue', () => { - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'label' }); - - let token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('label'); - expect(getInputValue()).toBe(''); - - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'label', tokenOperator: '=' }); - - token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('label'); - expect(token.querySelector('.operator').innerText).toBe('='); - expect(getInputValue()).toBe(''); - - FilteredSearchDropdownManager.addWordToInput({ - tokenName: 'label', - tokenOperator: '=', - tokenValue: 'none', - }); - // We have to get that reference again - // Because FilteredSearchDropdownManager deletes the previous token - token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('label'); - expect(token.querySelector('.operator').innerText).toBe('='); - expect(token.querySelector('.value').innerText).toBe('none'); - expect(getInputValue()).toBe(''); - }); - }); - - describe('input has existing value', () => { - it('should be able to just add tokenName', () => { - setInputValue('a'); - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'author' }); - - const token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('author'); - expect(getInputValue()).toBe(''); - }); - - it('should replace tokenValue', () => { - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'author' }); - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'author', tokenOperator: '=' }); - - setInputValue('roo'); - FilteredSearchDropdownManager.addWordToInput({ - tokenName: null, - tokenOperator: '=', - tokenValue: '@root', - }); - - const token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('author'); - expect(token.querySelector('.operator').innerText).toBe('='); - expect(token.querySelector('.value').innerText).toBe('@root'); - expect(getInputValue()).toBe(''); - }); - - it('should add tokenValues containing spaces', () => { - FilteredSearchDropdownManager.addWordToInput({ tokenName: 'label' }); - - setInputValue('"test '); - FilteredSearchDropdownManager.addWordToInput({ - tokenName: 'label', - tokenOperator: '=', - tokenValue: '~\'"test me"\'', - }); - - const token = document.querySelector('.tokens-container .js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toBe('label'); - expect(token.querySelector('.operator').innerText).toBe('='); - expect(token.querySelector('.value').innerText).toBe('~\'"test me"\''); - expect(getInputValue()).toBe(''); - }); - }); - }); -}); diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js deleted file mode 100644 index fda078bd41c..00000000000 --- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js +++ /dev/null @@ -1,722 +0,0 @@ -import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens'; -import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper'; - -describe('Filtered Search Visual Tokens', () => { - const subject = FilteredSearchVisualTokens; - - const findElements = tokenElement => { - const tokenNameElement = tokenElement.querySelector('.name'); - const tokenOperatorElement = tokenElement.querySelector('.operator'); - const tokenValueContainer = tokenElement.querySelector('.value-container'); - const tokenValueElement = tokenValueContainer.querySelector('.value'); - return { tokenNameElement, tokenOperatorElement, tokenValueContainer, tokenValueElement }; - }; - - let tokensContainer; - let authorToken; - let bugLabelToken; - - beforeEach(() => { - setFixtures(` - <ul class="tokens-container"> - ${FilteredSearchSpecHelper.createInputHTML()} - </ul> - `); - tokensContainer = document.querySelector('.tokens-container'); - - authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user'); - bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '=', '~bug'); - }); - - describe('getLastVisualTokenBeforeInput', () => { - it('returns when there are no visual tokens', () => { - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - - expect(lastVisualToken).toEqual(null); - expect(isLastVisualTokenValid).toEqual(true); - }); - - describe('input is the last item in tokensContainer', () => { - it('returns when there is one visual token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - bugLabelToken.outerHTML, - ); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - - expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token')); - expect(isLastVisualTokenValid).toEqual(true); - }); - - it('returns when there is an incomplete visual token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('Author'), - ); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - - expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token')); - expect(isLastVisualTokenValid).toEqual(false); - }); - - it('returns when there are multiple visual tokens', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${bugLabelToken.outerHTML} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root')} - `); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - const items = document.querySelectorAll('.tokens-container .js-visual-token'); - - expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true); - expect(isLastVisualTokenValid).toEqual(true); - }); - - it('returns when there are multiple visual tokens and an incomplete visual token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${bugLabelToken.outerHTML} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')} - ${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('assignee')} - `); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - const items = document.querySelectorAll('.tokens-container .js-visual-token'); - - expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true); - expect(isLastVisualTokenValid).toEqual(false); - }); - }); - - describe('input is a middle item in tokensContainer', () => { - it('returns last token before input', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${bugLabelToken.outerHTML} - ${FilteredSearchSpecHelper.createInputHTML()} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root')} - `); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - - expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token')); - expect(isLastVisualTokenValid).toEqual(true); - }); - - it('returns last partial token before input', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('label')} - ${FilteredSearchSpecHelper.createInputHTML()} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root')} - `); - - const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput(); - - expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token')); - expect(isLastVisualTokenValid).toEqual(false); - }); - }); - }); - - describe('getEndpointWithQueryParams', () => { - it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => { - const endpoint = 'foo/bar/-/labels.json'; - - expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint); - expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint); - expect(subject.getEndpointWithQueryParams(endpoint, '')).toBe(endpoint); - }); - - it('returns `endpoint` string with values of `endpointQueryParams`', () => { - const endpoint = 'foo/bar/-/labels.json'; - const singleQueryParams = '{"foo":"true"}'; - const multipleQueryParams = '{"foo":"true","bar":"true"}'; - - expect(subject.getEndpointWithQueryParams(endpoint, singleQueryParams)).toBe( - `${endpoint}?foo=true`, - ); - - expect(subject.getEndpointWithQueryParams(endpoint, multipleQueryParams)).toBe( - `${endpoint}?foo=true&bar=true`, - ); - }); - }); - - describe('unselectTokens', () => { - it('does nothing when there are no tokens', () => { - const beforeHTML = tokensContainer.innerHTML; - subject.unselectTokens(); - - expect(tokensContainer.innerHTML).toEqual(beforeHTML); - }); - - it('removes the selected class from buttons', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@author')} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', '%123', true)} - `); - - const selected = tokensContainer.querySelector('.js-visual-token .selected'); - - expect(selected.classList.contains('selected')).toEqual(true); - - subject.unselectTokens(); - - expect(selected.classList.contains('selected')).toEqual(false); - }); - }); - - describe('selectToken', () => { - beforeEach(() => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${bugLabelToken.outerHTML} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~awesome')} - `); - }); - - it('removes the selected class if it has selected class', () => { - const firstTokenButton = tokensContainer.querySelector('.js-visual-token .selectable'); - firstTokenButton.classList.add('selected'); - - subject.selectToken(firstTokenButton); - - expect(firstTokenButton.classList.contains('selected')).toEqual(false); - }); - - describe('has no selected class', () => { - it('adds selected class', () => { - const firstTokenButton = tokensContainer.querySelector('.js-visual-token .selectable'); - - subject.selectToken(firstTokenButton); - - expect(firstTokenButton.classList.contains('selected')).toEqual(true); - }); - - it('removes selected class from other tokens', () => { - const tokenButtons = tokensContainer.querySelectorAll('.js-visual-token .selectable'); - tokenButtons[1].classList.add('selected'); - - subject.selectToken(tokenButtons[0]); - - expect(tokenButtons[0].classList.contains('selected')).toEqual(true); - expect(tokenButtons[1].classList.contains('selected')).toEqual(false); - }); - }); - }); - - describe('removeSelectedToken', () => { - it('does not remove when there are no selected tokens', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none'), - ); - - expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null); - - subject.removeSelectedToken(); - - expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null); - }); - - it('removes selected token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none', true), - ); - - expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null); - - subject.removeSelectedToken(); - - expect(tokensContainer.querySelector('.js-visual-token .selectable')).toEqual(null); - }); - }); - - describe('createVisualTokenElementHTML', () => { - let tokenElement; - - beforeEach(() => { - setFixtures(` - <div class="test-area"> - ${subject.createVisualTokenElementHTML('custom-token')} - </div> - `); - - tokenElement = document.querySelector('.test-area').firstElementChild; - }); - - it('should add class name to token element', () => { - expect(document.querySelector('.test-area .custom-token')).toBeDefined(); - }); - - it('contains name div', () => { - expect(tokenElement.querySelector('.name')).toEqual(jasmine.anything()); - }); - - it('contains value container div', () => { - expect(tokenElement.querySelector('.value-container')).toEqual(jasmine.anything()); - }); - - it('contains value div', () => { - expect(tokenElement.querySelector('.value-container .value')).toEqual(jasmine.anything()); - }); - - it('contains selectable class', () => { - expect(tokenElement.classList.contains('selectable')).toEqual(true); - }); - - it('contains button role', () => { - expect(tokenElement.getAttribute('role')).toEqual('button'); - }); - - describe('remove token', () => { - it('contains remove-token button', () => { - expect(tokenElement.querySelector('.value-container .remove-token')).toEqual( - jasmine.anything(), - ); - }); - - it('contains fa-close icon', () => { - expect(tokenElement.querySelector('.remove-token .fa-close')).toEqual(jasmine.anything()); - }); - }); - }); - - describe('addVisualTokenElement', () => { - it('renders search visual tokens', () => { - subject.addVisualTokenElement({ - name: 'search term', - operator: '=', - value: null, - options: { isSearchTerm: true }, - }); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('filtered-search-term')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('search term'); - expect(token.querySelector('.operator').innerText).toEqual('='); - expect(token.querySelector('.value')).toEqual(null); - }); - - it('renders filter visual token name', () => { - subject.addVisualTokenElement({ name: 'milestone' }); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('search-token-milestone')).toEqual(true); - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('milestone'); - expect(token.querySelector('.value')).toEqual(null); - }); - - it('renders filter visual token name, operator, and value', () => { - subject.addVisualTokenElement({ name: 'label', operator: '!=', value: 'Frontend' }); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('search-token-label')).toEqual(true); - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('label'); - expect(token.querySelector('.operator').innerText).toEqual('!='); - expect(token.querySelector('.value').innerText).toEqual('Frontend'); - }); - - it('inserts visual token before input', () => { - tokensContainer.appendChild( - FilteredSearchSpecHelper.createFilterVisualToken('assignee', '=', '@root'), - ); - - subject.addVisualTokenElement({ name: 'label', operator: '!=', value: 'Frontend' }); - const tokens = tokensContainer.querySelectorAll('.js-visual-token'); - const labelToken = tokens[0]; - const assigneeToken = tokens[1]; - - expect(labelToken.classList.contains('search-token-label')).toEqual(true); - expect(labelToken.classList.contains('filtered-search-token')).toEqual(true); - expect(labelToken.querySelector('.name').innerText).toEqual('label'); - expect(labelToken.querySelector('.value').innerText).toEqual('Frontend'); - expect(labelToken.querySelector('.operator').innerText).toEqual('!='); - - expect(assigneeToken.classList.contains('search-token-assignee')).toEqual(true); - expect(assigneeToken.classList.contains('filtered-search-token')).toEqual(true); - expect(assigneeToken.querySelector('.name').innerText).toEqual('assignee'); - expect(assigneeToken.querySelector('.value').innerText).toEqual('@root'); - expect(assigneeToken.querySelector('.operator').innerText).toEqual('='); - }); - }); - - describe('addValueToPreviousVisualTokenElement', () => { - it('does not add when previous visual token element has no value', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root'), - ); - - const original = tokensContainer.innerHTML; - subject.addValueToPreviousVisualTokenElement('value'); - - expect(original).toEqual(tokensContainer.innerHTML); - }); - - it('does not add when previous visual token element is a search', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root')} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')} - `); - - const original = tokensContainer.innerHTML; - subject.addValueToPreviousVisualTokenElement('value'); - - expect(original).toEqual(tokensContainer.innerHTML); - }); - - it('adds value to previous visual filter token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createNameOperatorFilterVisualTokenHTML('label', '='), - ); - - const original = tokensContainer.innerHTML; - subject.addValueToPreviousVisualTokenElement('value'); - const updatedToken = tokensContainer.querySelector('.js-visual-token'); - - expect(updatedToken.querySelector('.name').innerText).toEqual('label'); - expect(updatedToken.querySelector('.value').innerText).toEqual('value'); - expect(original).not.toEqual(tokensContainer.innerHTML); - }); - }); - - describe('addFilterVisualToken', () => { - it('creates visual token with just tokenName', () => { - subject.addFilterVisualToken('milestone'); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('milestone'); - expect(token.querySelector('.operator')).toEqual(null); - expect(token.querySelector('.value')).toEqual(null); - }); - - it('creates visual token with just tokenValue', () => { - subject.addFilterVisualToken('milestone', '='); - subject.addFilterVisualToken('%8.17'); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('milestone'); - expect(token.querySelector('.operator').innerText).toEqual('='); - expect(token.querySelector('.value').innerText).toEqual('%8.17'); - }); - - it('creates full visual token', () => { - subject.addFilterVisualToken('assignee', '=', '@john'); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('filtered-search-token')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('assignee'); - expect(token.querySelector('.operator').innerText).toEqual('='); - expect(token.querySelector('.value').innerText).toEqual('@john'); - }); - }); - - describe('addSearchVisualToken', () => { - it('creates search visual token', () => { - subject.addSearchVisualToken('search term'); - const token = tokensContainer.querySelector('.js-visual-token'); - - expect(token.classList.contains('filtered-search-term')).toEqual(true); - expect(token.querySelector('.name').innerText).toEqual('search term'); - expect(token.querySelector('.value')).toEqual(null); - }); - - it('appends to previous search visual token if previous token was a search token', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '=', '@root')} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')} - `); - - subject.addSearchVisualToken('append this'); - const token = tokensContainer.querySelector('.filtered-search-term'); - - expect(token.querySelector('.name').innerText).toEqual('search term append this'); - expect(token.querySelector('.value')).toEqual(null); - }); - }); - - describe('getLastTokenPartial', () => { - it('should get last token value', () => { - const value = '~bug'; - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - bugLabelToken.outerHTML, - ); - - expect(subject.getLastTokenPartial()).toEqual(value); - }); - - it('should get last token original value if available', () => { - const originalValue = '@user'; - const valueContainer = authorToken.querySelector('.value-container'); - valueContainer.dataset.originalValue = originalValue; - const avatar = document.createElement('img'); - const valueElement = valueContainer.querySelector('.value'); - valueElement.insertAdjacentElement('afterbegin', avatar); - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - authorToken.outerHTML, - ); - - const lastTokenValue = subject.getLastTokenPartial(); - - expect(lastTokenValue).toEqual(originalValue); - }); - - it('should get last token name if there is no value', () => { - const name = 'assignee'; - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createNameFilterVisualTokenHTML(name), - ); - - expect(subject.getLastTokenPartial()).toEqual(name); - }); - - it('should return empty when there are no tokens', () => { - expect(subject.getLastTokenPartial()).toEqual(''); - }); - }); - - describe('removeLastTokenPartial', () => { - it('should remove the last token value if it exists', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML( - 'label', - '=', - '~"Community Contribution"', - ), - ); - - expect(tokensContainer.querySelector('.js-visual-token .value')).not.toEqual(null); - - subject.removeLastTokenPartial(); - - expect(tokensContainer.querySelector('.js-visual-token .value')).toEqual(null); - }); - - it('should remove the last token name if there is no value', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('milestone'), - ); - - expect(tokensContainer.querySelector('.js-visual-token .name')).not.toEqual(null); - - subject.removeLastTokenPartial(); - - expect(tokensContainer.querySelector('.js-visual-token .name')).toEqual(null); - }); - - it('should not remove anything when there are no tokens', () => { - const html = tokensContainer.innerHTML; - subject.removeLastTokenPartial(); - - expect(tokensContainer.innerHTML).toEqual(html); - }); - }); - - describe('tokenizeInput', () => { - it('does not do anything if there is no input', () => { - const original = tokensContainer.innerHTML; - subject.tokenizeInput(); - - expect(tokensContainer.innerHTML).toEqual(original); - }); - - it('adds search visual token if previous visual token is valid', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML('assignee', '=', 'none'), - ); - - const input = document.querySelector('.filtered-search'); - input.value = 'some value'; - subject.tokenizeInput(); - - const newToken = tokensContainer.querySelector('.filtered-search-term'); - - expect(input.value).toEqual(''); - expect(newToken.querySelector('.name').innerText).toEqual('some value'); - expect(newToken.querySelector('.value')).toEqual(null); - }); - - it('adds value to previous visual token element if previous visual token is invalid', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createNameOperatorFilterVisualTokenHTML('assignee', '='), - ); - - const input = document.querySelector('.filtered-search'); - input.value = '@john'; - subject.tokenizeInput(); - - const updatedToken = tokensContainer.querySelector('.filtered-search-token'); - - expect(input.value).toEqual(''); - expect(updatedToken.querySelector('.name').innerText).toEqual('assignee'); - expect(updatedToken.querySelector('.operator').innerText).toEqual('='); - expect(updatedToken.querySelector('.value').innerText).toEqual('@john'); - }); - }); - - describe('editToken', () => { - let input; - let token; - - beforeEach(() => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none')} - ${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search')} - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'upcoming')} - `); - - input = document.querySelector('.filtered-search'); - token = document.querySelector('.js-visual-token'); - }); - - it("tokenize's existing input", () => { - input.value = 'some text'; - spyOn(subject, 'tokenizeInput').and.callThrough(); - - subject.editToken(token); - - expect(subject.tokenizeInput).toHaveBeenCalled(); - expect(input.value).not.toEqual('some text'); - }); - - it('moves input to the token position', () => { - expect(tokensContainer.children[3].querySelector('.filtered-search')).not.toEqual(null); - - subject.editToken(token); - - expect(tokensContainer.children[1].querySelector('.filtered-search')).not.toEqual(null); - expect(tokensContainer.children[3].querySelector('.filtered-search')).toEqual(null); - }); - - it('input contains the visual token value', () => { - subject.editToken(token); - - expect(input.value).toEqual('none'); - }); - - it('input contains the original value if present', () => { - const originalValue = '@user'; - const valueContainer = token.querySelector('.value-container'); - valueContainer.dataset.originalValue = originalValue; - - subject.editToken(token); - - expect(input.value).toEqual(originalValue); - }); - - describe('selected token is a search term token', () => { - beforeEach(() => { - token = document.querySelector('.filtered-search-term'); - }); - - it('token is removed', () => { - expect(tokensContainer.querySelector('.filtered-search-term')).not.toEqual(null); - - subject.editToken(token); - - expect(tokensContainer.querySelector('.filtered-search-term')).toEqual(null); - }); - - it('input has the same value as removed token', () => { - expect(input.value).toEqual(''); - - subject.editToken(token); - - expect(input.value).toEqual('search'); - }); - }); - }); - - describe('moveInputTotheRight', () => { - it('does nothing if the input is already the right most element', () => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( - FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none'), - ); - - spyOn(subject, 'tokenizeInput').and.callFake(() => {}); - spyOn(subject, 'getLastVisualTokenBeforeInput').and.callThrough(); - - subject.moveInputToTheRight(); - - expect(subject.tokenizeInput).toHaveBeenCalled(); - expect(subject.getLastVisualTokenBeforeInput).not.toHaveBeenCalled(); - }); - - it("tokenize's input", () => { - tokensContainer.innerHTML = ` - ${FilteredSearchSpecHelper.createNameOperatorFilterVisualTokenHTML('label', '=')} - ${FilteredSearchSpecHelper.createInputHTML()} - ${bugLabelToken.outerHTML} - `; - - tokensContainer.querySelector('.filtered-search').value = 'none'; - - subject.moveInputToTheRight(); - const value = tokensContainer.querySelector('.js-visual-token .value'); - - expect(value.innerText).toEqual('none'); - }); - - it('converts input into search term token if last token is valid', () => { - tokensContainer.innerHTML = ` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none')} - ${FilteredSearchSpecHelper.createInputHTML()} - ${bugLabelToken.outerHTML} - `; - - document.querySelector('.filtered-search').value = 'test'; - - subject.moveInputToTheRight(); - const searchValue = tokensContainer.querySelector('.filtered-search-term .name'); - - expect(searchValue.innerText).toEqual('test'); - }); - - it('moves the input to the right most element', () => { - tokensContainer.innerHTML = ` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none')} - ${FilteredSearchSpecHelper.createInputHTML()} - ${bugLabelToken.outerHTML} - `; - - subject.moveInputToTheRight(); - - expect(tokensContainer.children[2].querySelector('.filtered-search')).not.toEqual(null); - }); - - it('tokenizes input even if input is the right most element', () => { - tokensContainer.innerHTML = ` - ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none')} - ${FilteredSearchSpecHelper.createNameOperatorFilterVisualTokenHTML('label')} - ${FilteredSearchSpecHelper.createInputHTML('', '~bug')} - `; - - subject.moveInputToTheRight(); - - const token = tokensContainer.children[1]; - - expect(token.querySelector('.value').innerText).toEqual('~bug'); - }); - }); - - describe('renderVisualTokenValue', () => { - beforeEach(() => { - tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(` - ${authorToken.outerHTML} - ${bugLabelToken.outerHTML} - `); - }); - - it('renders a author token value element', () => { - const { tokenNameElement, tokenValueElement } = findElements(authorToken); - const tokenName = tokenNameElement.innerText; - const tokenValue = 'new value'; - - subject.renderVisualTokenValue(authorToken, tokenName, tokenValue); - - expect(tokenValueElement.innerText).toBe(tokenValue); - }); - }); -}); diff --git a/spec/javascripts/gl_form_spec.js b/spec/javascripts/gl_form_spec.js deleted file mode 100644 index 69b3dae743a..00000000000 --- a/spec/javascripts/gl_form_spec.js +++ /dev/null @@ -1,110 +0,0 @@ -import $ from 'jquery'; -import autosize from 'autosize'; -import GLForm from '~/gl_form'; -import '~/lib/utils/text_utility'; -import '~/lib/utils/common_utils'; - -describe('GLForm', () => { - describe('when instantiated', function() { - beforeEach(done => { - this.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>'); - this.textarea = this.form.find('textarea'); - spyOn($.prototype, 'off').and.returnValue(this.textarea); - spyOn($.prototype, 'on').and.returnValue(this.textarea); - spyOn($.prototype, 'css'); - - this.glForm = new GLForm(this.form, false); - setTimeout(() => { - $.prototype.off.calls.reset(); - $.prototype.on.calls.reset(); - $.prototype.css.calls.reset(); - done(); - }); - }); - - describe('setupAutosize', () => { - beforeEach(done => { - this.glForm.setupAutosize(); - setTimeout(() => { - done(); - }); - }); - - it('should register an autosize event handler on the textarea', () => { - expect($.prototype.off).toHaveBeenCalledWith('autosize:resized'); - expect($.prototype.on).toHaveBeenCalledWith('autosize:resized', jasmine.any(Function)); - }); - - it('should register a mouseup event handler on the textarea', () => { - expect($.prototype.off).toHaveBeenCalledWith('mouseup.autosize'); - expect($.prototype.on).toHaveBeenCalledWith('mouseup.autosize', jasmine.any(Function)); - }); - - it('should set the resize css property to vertical', () => { - expect($.prototype.css).toHaveBeenCalledWith('resize', 'vertical'); - }); - }); - - describe('setHeightData', () => { - beforeEach(() => { - spyOn($.prototype, 'data'); - spyOn($.prototype, 'outerHeight').and.returnValue(200); - this.glForm.setHeightData(); - }); - - it('should set the height data attribute', () => { - expect($.prototype.data).toHaveBeenCalledWith('height', 200); - }); - - it('should call outerHeight', () => { - expect($.prototype.outerHeight).toHaveBeenCalled(); - }); - }); - - describe('destroyAutosize', () => { - describe('when called', () => { - beforeEach(() => { - spyOn($.prototype, 'data'); - spyOn($.prototype, 'outerHeight').and.returnValue(200); - spyOn(window, 'outerHeight').and.returnValue(400); - spyOn(autosize, 'destroy'); - - this.glForm.destroyAutosize(); - }); - - it('should call outerHeight', () => { - expect($.prototype.outerHeight).toHaveBeenCalled(); - }); - - it('should get data-height attribute', () => { - expect($.prototype.data).toHaveBeenCalledWith('height'); - }); - - it('should call autosize destroy', () => { - expect(autosize.destroy).toHaveBeenCalledWith(this.textarea); - }); - - it('should set the data-height attribute', () => { - expect($.prototype.data).toHaveBeenCalledWith('height', 200); - }); - - it('should set the outerHeight', () => { - expect($.prototype.outerHeight).toHaveBeenCalledWith(200); - }); - - it('should set the css', () => { - expect($.prototype.css).toHaveBeenCalledWith('max-height', window.outerHeight); - }); - }); - - it('should return undefined if the data-height equals the outerHeight', () => { - spyOn($.prototype, 'outerHeight').and.returnValue(200); - spyOn($.prototype, 'data').and.returnValue(200); - spyOn(autosize, 'destroy'); - - expect(this.glForm.destroyAutosize()).toBeUndefined(); - expect(autosize.destroy).not.toHaveBeenCalled(); - }); - }); - }); -}); diff --git a/spec/javascripts/global_search_input_spec.js b/spec/javascripts/global_search_input_spec.js deleted file mode 100644 index 00ae8a8f2ea..00000000000 --- a/spec/javascripts/global_search_input_spec.js +++ /dev/null @@ -1,215 +0,0 @@ -/* eslint-disable no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign */ - -import $ from 'jquery'; -import '~/gl_dropdown'; -import initGlobalSearchInput from '~/global_search_input'; -import '~/lib/utils/common_utils'; - -describe('Global search input dropdown', () => { - let widget = null; - - const userName = 'root'; - - const userId = 1; - - const dashboardIssuesPath = '/dashboard/issues'; - - const dashboardMRsPath = '/dashboard/merge_requests'; - - const projectIssuesPath = '/gitlab-org/gitlab-foss/issues'; - - const projectMRsPath = '/gitlab-org/gitlab-foss/-/merge_requests'; - - const groupIssuesPath = '/groups/gitlab-org/-/issues'; - - const groupMRsPath = '/groups/gitlab-org/-/merge_requests'; - - const projectName = 'GitLab Community Edition'; - - const groupName = 'Gitlab Org'; - - const removeBodyAttributes = function() { - const $body = $('body'); - - $body.removeAttr('data-page'); - $body.removeAttr('data-project'); - $body.removeAttr('data-group'); - }; - - // Add required attributes to body before starting the test. - // section would be dashboard|group|project - const addBodyAttributes = function(section) { - if (section == null) { - section = 'dashboard'; - } - - const $body = $('body'); - removeBodyAttributes(); - switch (section) { - case 'dashboard': - return $body.attr('data-page', 'root:index'); - case 'group': - $body.attr('data-page', 'groups:show'); - return $body.data('group', 'gitlab-org'); - case 'project': - $body.attr('data-page', 'projects:show'); - return $body.data('project', 'gitlab-ce'); - } - }; - - const disableProjectIssues = function() { - document.querySelector('.js-search-project-options').setAttribute('data-issues-disabled', true); - }; - - // Mock `gl` object in window for dashboard specific page. App code will need it. - const mockDashboardOptions = function() { - window.gl || (window.gl = {}); - return (window.gl.dashboardOptions = { - issuesPath: dashboardIssuesPath, - mrPath: dashboardMRsPath, - }); - }; - - // Mock `gl` object in window for project specific page. App code will need it. - const mockProjectOptions = function() { - window.gl || (window.gl = {}); - return (window.gl.projectOptions = { - 'gitlab-ce': { - issuesPath: projectIssuesPath, - mrPath: projectMRsPath, - projectName, - }, - }); - }; - - const mockGroupOptions = function() { - window.gl || (window.gl = {}); - return (window.gl.groupOptions = { - 'gitlab-org': { - issuesPath: groupIssuesPath, - mrPath: groupMRsPath, - projectName: groupName, - }, - }); - }; - - const assertLinks = function(list, issuesPath, mrsPath) { - if (issuesPath) { - const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_username=${userName}"]`; - const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_username=${userName}"]`; - - expect(list.find(issuesAssignedToMeLink).length).toBe(1); - expect(list.find(issuesAssignedToMeLink).text()).toBe('Issues assigned to me'); - expect(list.find(issuesIHaveCreatedLink).length).toBe(1); - expect(list.find(issuesIHaveCreatedLink).text()).toBe("Issues I've created"); - } - const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_username=${userName}"]`; - const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_username=${userName}"]`; - - expect(list.find(mrsAssignedToMeLink).length).toBe(1); - expect(list.find(mrsAssignedToMeLink).text()).toBe('Merge requests assigned to me'); - expect(list.find(mrsIHaveCreatedLink).length).toBe(1); - expect(list.find(mrsIHaveCreatedLink).text()).toBe("Merge requests I've created"); - }; - - preloadFixtures('static/global_search_input.html'); - beforeEach(function() { - loadFixtures('static/global_search_input.html'); - - window.gon = {}; - window.gon.current_user_id = userId; - window.gon.current_username = userName; - - return (widget = initGlobalSearchInput()); - }); - - afterEach(function() { - // Undo what we did to the shared <body> - removeBodyAttributes(); - window.gon = {}; - }); - - it('should show Dashboard specific dropdown menu', function() { - addBodyAttributes(); - mockDashboardOptions(); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, dashboardIssuesPath, dashboardMRsPath); - }); - - it('should show Group specific dropdown menu', function() { - addBodyAttributes('group'); - mockGroupOptions(); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, groupIssuesPath, groupMRsPath); - }); - - it('should show Project specific dropdown menu', function() { - addBodyAttributes('project'); - mockProjectOptions(); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - return assertLinks(list, projectIssuesPath, projectMRsPath); - }); - - it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() { - addBodyAttributes('project'); - disableProjectIssues(); - mockProjectOptions(); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - assertLinks(list, null, projectMRsPath); - }); - - it('should not show category related menu if there is text in the input', function() { - addBodyAttributes('project'); - mockProjectOptions(); - widget.searchInput.val('help'); - widget.searchInput.triggerHandler('focus'); - const list = widget.wrap.find('.dropdown-menu').find('ul'); - const link = `a[href='${projectIssuesPath}/?assignee_username=${userName}']`; - - expect(list.find(link).length).toBe(0); - }); - - it('should not submit the search form when selecting an autocomplete row with the keyboard', function() { - const ENTER = 13; - const DOWN = 40; - addBodyAttributes(); - mockDashboardOptions(true); - const submitSpy = spyOnEvent('form', 'submit'); - widget.searchInput.triggerHandler('focus'); - widget.wrap.trigger($.Event('keydown', { which: DOWN })); - const enterKeyEvent = $.Event('keydown', { which: ENTER }); - widget.searchInput.trigger(enterKeyEvent); - // This does not currently catch failing behavior. For security reasons, - // browsers will not trigger default behavior (form submit, in this - // example) on JavaScript-created keypresses. - expect(submitSpy).not.toHaveBeenTriggered(); - }); - - describe('disableDropdown', function() { - beforeEach(function() { - widget.enableDropdown(); - }); - - it('should close the Dropdown', function() { - const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown'); - - widget.dropdown.addClass('show'); - widget.disableDropdown(); - - expect(toggleSpy).toHaveBeenCalledWith('toggle'); - }); - }); - - describe('enableDropdown', function() { - it('should open the Dropdown', function() { - const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown'); - widget.enableDropdown(); - - expect(toggleSpy).toHaveBeenCalledWith('toggle'); - }); - }); -}); diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js deleted file mode 100644 index 94e833ec83b..00000000000 --- a/spec/javascripts/labels_issue_sidebar_spec.js +++ /dev/null @@ -1,97 +0,0 @@ -/* eslint-disable no-new */ - -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import { shuffle } from 'lodash'; -import axios from '~/lib/utils/axios_utils'; -import IssuableContext from '~/issuable_context'; -import LabelsSelect from '~/labels_select'; - -import '~/gl_dropdown'; -import 'select2'; -import '~/api'; -import '~/create_label'; -import '~/users_select'; - -let saveLabelCount = 0; -let mock; - -function testLabelClicks(labelOrder, done) { - $('.edit-link') - .get(0) - .click(); - - setTimeout(() => { - const labelsInDropdown = $('.dropdown-content a'); - - expect(labelsInDropdown.length).toBe(10); - - const arrayOfLabels = labelsInDropdown.get(); - const randomArrayOfLabels = shuffle(arrayOfLabels); - randomArrayOfLabels.forEach((label, i) => { - if (i < saveLabelCount) { - $(label).click(); - } - }); - - $('.edit-link') - .get(0) - .click(); - - setTimeout(() => { - expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe(labelOrder); - done(); - }, 0); - }, 0); -} - -describe('Issue dropdown sidebar', () => { - preloadFixtures('static/issue_sidebar_label.html'); - - beforeEach(() => { - loadFixtures('static/issue_sidebar_label.html'); - - mock = new MockAdapter(axios); - - new IssuableContext('{"id":1,"name":"Administrator","username":"root"}'); - new LabelsSelect(); - - mock.onGet('/root/test/labels.json').reply(() => { - const labels = Array(10) - .fill() - .map((_val, i) => ({ - id: i, - title: `test ${i}`, - color: '#5CB85C', - })); - - return [200, labels]; - }); - - mock.onPut('/root/test/issues/2.json').reply(() => { - const labels = Array(saveLabelCount) - .fill() - .map((_val, i) => ({ - id: i, - title: `test ${i}`, - color: '#5CB85C', - })); - - return [200, { labels }]; - }); - }); - - afterEach(() => { - mock.restore(); - }); - - it('changes collapsed tooltip when changing labels when less than 5', done => { - saveLabelCount = 5; - testLabelClicks('test 0, test 1, test 2, test 3, test 4', done); - }); - - it('changes collapsed tooltip when changing labels when more than 5', done => { - saveLabelCount = 6; - testLabelClicks('test 0, test 1, test 2, test 3, test 4, and 1 more', done); - }); -}); diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js deleted file mode 100644 index bedab0fd003..00000000000 --- a/spec/javascripts/line_highlighter_spec.js +++ /dev/null @@ -1,261 +0,0 @@ -/* eslint-disable dot-notation, no-return-assign, no-new, no-underscore-dangle */ - -import $ from 'jquery'; -import LineHighlighter from '~/line_highlighter'; - -describe('LineHighlighter', function() { - preloadFixtures('static/line_highlighter.html'); - const clickLine = function(number, eventData = {}) { - if ($.isEmptyObject(eventData)) { - return $(`#L${number}`).click(); - } - const e = $.Event('click', eventData); - return $(`#L${number}`).trigger(e); - }; - beforeEach(function() { - loadFixtures('static/line_highlighter.html'); - this['class'] = new LineHighlighter(); - this.css = this['class'].highlightLineClass; - return (this.spies = { - __setLocationHash__: spyOn(this['class'], '__setLocationHash__').and.callFake(function() {}), - }); - }); - - describe('behavior', function() { - it('highlights one line given in the URL hash', function() { - new LineHighlighter({ hash: '#L13' }); - - expect($('#LC13')).toHaveClass(this.css); - }); - - it('highlights one line given in the URL hash with given CSS class name', function() { - const hiliter = new LineHighlighter({ hash: '#L13', highlightLineClass: 'hilite' }); - - expect(hiliter.highlightLineClass).toBe('hilite'); - expect($('#LC13')).toHaveClass('hilite'); - expect($('#LC13')).not.toHaveClass('hll'); - }); - - it('highlights a range of lines given in the URL hash', function() { - new LineHighlighter({ hash: '#L5-25' }); - - expect($(`.${this.css}`).length).toBe(21); - for (let line = 5; line <= 25; line += 1) { - expect($(`#LC${line}`)).toHaveClass(this.css); - } - }); - - it('scrolls to the first highlighted line on initial load', function() { - const spy = spyOn($, 'scrollTo'); - new LineHighlighter({ hash: '#L5-25' }); - - expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything()); - }); - - it('discards click events', function() { - const spy = spyOnEvent('a[data-line-number]', 'click'); - clickLine(13); - - expect(spy).toHaveBeenPrevented(); - }); - - it('handles garbage input from the hash', function() { - const func = function() { - return new LineHighlighter({ fileHolderSelector: '#blob-content-holder' }); - }; - - expect(func).not.toThrow(); - }); - - it('handles hashchange event', () => { - const highlighter = new LineHighlighter(); - - spyOn(highlighter, 'highlightHash'); - - window.dispatchEvent(new Event('hashchange'), 'L15'); - - expect(highlighter.highlightHash).toHaveBeenCalled(); - }); - }); - - describe('clickHandler', function() { - it('handles clicking on a child icon element', function() { - const spy = spyOn(this['class'], 'setHash').and.callThrough(); - $('#L13 i') - .mousedown() - .click(); - - expect(spy).toHaveBeenCalledWith(13); - expect($('#LC13')).toHaveClass(this.css); - }); - - describe('without shiftKey', function() { - it('highlights one line when clicked', function() { - clickLine(13); - - expect($('#LC13')).toHaveClass(this.css); - }); - - it('unhighlights previously highlighted lines', function() { - clickLine(13); - clickLine(20); - - expect($('#LC13')).not.toHaveClass(this.css); - expect($('#LC20')).toHaveClass(this.css); - }); - - it('sets the hash', function() { - const spy = spyOn(this['class'], 'setHash').and.callThrough(); - clickLine(13); - - expect(spy).toHaveBeenCalledWith(13); - }); - }); - - describe('with shiftKey', function() { - it('sets the hash', function() { - const spy = spyOn(this['class'], 'setHash').and.callThrough(); - clickLine(13); - clickLine(20, { - shiftKey: true, - }); - - expect(spy).toHaveBeenCalledWith(13); - expect(spy).toHaveBeenCalledWith(13, 20); - }); - - describe('without existing highlight', function() { - it('highlights the clicked line', function() { - clickLine(13, { - shiftKey: true, - }); - - expect($('#LC13')).toHaveClass(this.css); - expect($(`.${this.css}`).length).toBe(1); - }); - - it('sets the hash', function() { - const spy = spyOn(this['class'], 'setHash'); - clickLine(13, { - shiftKey: true, - }); - - expect(spy).toHaveBeenCalledWith(13); - }); - }); - - describe('with existing single-line highlight', function() { - it('uses existing line as last line when target is lesser', function() { - clickLine(20); - clickLine(15, { - shiftKey: true, - }); - - expect($(`.${this.css}`).length).toBe(6); - for (let line = 15; line <= 20; line += 1) { - expect($(`#LC${line}`)).toHaveClass(this.css); - } - }); - - it('uses existing line as first line when target is greater', function() { - clickLine(5); - clickLine(10, { - shiftKey: true, - }); - - expect($(`.${this.css}`).length).toBe(6); - for (let line = 5; line <= 10; line += 1) { - expect($(`#LC${line}`)).toHaveClass(this.css); - } - }); - }); - - describe('with existing multi-line highlight', function() { - beforeEach(function() { - clickLine(10, { - shiftKey: true, - }); - clickLine(13, { - shiftKey: true, - }); - }); - - it('uses target as first line when it is less than existing first line', function() { - clickLine(5, { - shiftKey: true, - }); - - expect($(`.${this.css}`).length).toBe(6); - for (let line = 5; line <= 10; line += 1) { - expect($(`#LC${line}`)).toHaveClass(this.css); - } - }); - - it('uses target as last line when it is greater than existing first line', function() { - clickLine(15, { - shiftKey: true, - }); - - expect($(`.${this.css}`).length).toBe(6); - for (let line = 10; line <= 15; line += 1) { - expect($(`#LC${line}`)).toHaveClass(this.css); - } - }); - }); - }); - }); - - describe('hashToRange', function() { - beforeEach(function() { - this.subject = this['class'].hashToRange; - }); - - it('extracts a single line number from the hash', function() { - expect(this.subject('#L5')).toEqual([5, null]); - }); - - it('extracts a range of line numbers from the hash', function() { - expect(this.subject('#L5-15')).toEqual([5, 15]); - }); - - it('returns [null, null] when the hash is not a line number', function() { - expect(this.subject('#foo')).toEqual([null, null]); - }); - }); - - describe('highlightLine', function() { - beforeEach(function() { - this.subject = this['class'].highlightLine; - }); - - it('highlights the specified line', function() { - this.subject(13); - - expect($('#LC13')).toHaveClass(this.css); - }); - - it('accepts a String-based number', function() { - this.subject('13'); - - expect($('#LC13')).toHaveClass(this.css); - }); - }); - - describe('setHash', function() { - beforeEach(function() { - this.subject = this['class'].setHash; - }); - - it('sets the location hash for a single line', function() { - this.subject(5); - - expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5'); - }); - - it('sets the location hash for a range', function() { - this.subject(5, 15); - - expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5-15'); - }); - }); -}); diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js deleted file mode 100644 index 2b5fde9532d..00000000000 --- a/spec/javascripts/merge_request_tabs_spec.js +++ /dev/null @@ -1,294 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import MergeRequestTabs from '~/merge_request_tabs'; -import '~/commit/pipelines/pipelines_bundle'; -import '~/lib/utils/common_utils'; -import 'vendor/jquery.scrollTo'; -import initMrPage from './helpers/init_vue_mr_page_helper'; - -describe('MergeRequestTabs', function() { - let mrPageMock; - const stubLocation = {}; - const setLocation = function(stubs) { - const defaults = { - pathname: '', - search: '', - hash: '', - }; - $.extend(stubLocation, defaults, stubs || {}); - }; - - preloadFixtures( - 'merge_requests/merge_request_with_task_list.html', - 'merge_requests/diff_comment.html', - ); - - beforeEach(function() { - mrPageMock = initMrPage(); - this.class = new MergeRequestTabs({ stubLocation }); - setLocation(); - - this.spies = { - history: spyOn(window.history, 'pushState').and.callFake(function() {}), - }; - }); - - afterEach(function() { - this.class.unbindEvents(); - this.class.destroyPipelinesView(); - mrPageMock.restore(); - $('.js-merge-request-test').remove(); - }); - - describe('opensInNewTab', function() { - const windowTarget = '_blank'; - let clickTabParams; - let tabUrl; - - beforeEach(function() { - loadFixtures('merge_requests/merge_request_with_task_list.html'); - - tabUrl = $('.commits-tab a').attr('href'); - - clickTabParams = { - metaKey: false, - ctrlKey: false, - which: 1, - stopImmediatePropagation() {}, - preventDefault() {}, - currentTarget: { - getAttribute(attr) { - return attr === 'href' ? tabUrl : null; - }, - }, - }; - }); - - describe('meta click', () => { - let metakeyEvent; - - beforeEach(function() { - metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true }); - }); - - it('opens page when commits link is clicked', function() { - spyOn(window, 'open').and.callFake(function(url, name) { - expect(url).toEqual(tabUrl); - expect(name).toEqual(windowTarget); - }); - - this.class.bindEvents(); - $('.merge-request-tabs .commits-tab a').trigger(metakeyEvent); - - expect(window.open).toHaveBeenCalled(); - }); - - it('opens page when commits badge is clicked', function() { - spyOn(window, 'open').and.callFake(function(url, name) { - expect(url).toEqual(tabUrl); - expect(name).toEqual(windowTarget); - }); - - this.class.bindEvents(); - $('.merge-request-tabs .commits-tab a .badge').trigger(metakeyEvent); - - expect(window.open).toHaveBeenCalled(); - }); - }); - - it('opens page tab in a new browser tab with Ctrl+Click - Windows/Linux', function() { - spyOn(window, 'open').and.callFake(function(url, name) { - expect(url).toEqual(tabUrl); - expect(name).toEqual(windowTarget); - }); - - this.class.clickTab({ ...clickTabParams, metaKey: true }); - - expect(window.open).toHaveBeenCalled(); - }); - - it('opens page tab in a new browser tab with Cmd+Click - Mac', function() { - spyOn(window, 'open').and.callFake(function(url, name) { - expect(url).toEqual(tabUrl); - expect(name).toEqual(windowTarget); - }); - - this.class.clickTab({ ...clickTabParams, ctrlKey: true }); - - expect(window.open).toHaveBeenCalled(); - }); - - it('opens page tab in a new browser tab with Middle-click - Mac/PC', function() { - spyOn(window, 'open').and.callFake(function(url, name) { - expect(url).toEqual(tabUrl); - expect(name).toEqual(windowTarget); - }); - - this.class.clickTab({ ...clickTabParams, which: 2 }); - - expect(window.open).toHaveBeenCalled(); - }); - }); - - describe('setCurrentAction', function() { - let mock; - - beforeEach(function() { - mock = new MockAdapter(axios); - mock.onAny().reply({ data: {} }); - this.subject = this.class.setCurrentAction; - }); - - afterEach(() => { - mock.restore(); - window.history.replaceState({}, '', '/'); - }); - - it('changes from commits', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1/commits', - }); - - expect(this.subject('show')).toBe('/foo/bar/-/merge_requests/1'); - expect(this.subject('diffs')).toBe('/foo/bar/-/merge_requests/1/diffs'); - }); - - it('changes from diffs', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1/diffs', - }); - - expect(this.subject('show')).toBe('/foo/bar/-/merge_requests/1'); - expect(this.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); - }); - - it('changes from diffs.html', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1/diffs.html', - }); - - expect(this.subject('show')).toBe('/foo/bar/-/merge_requests/1'); - expect(this.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); - }); - - it('changes from notes', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1', - }); - - expect(this.subject('diffs')).toBe('/foo/bar/-/merge_requests/1/diffs'); - expect(this.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); - }); - - it('includes search parameters and hash string', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1/diffs', - search: '?view=parallel', - hash: '#L15-35', - }); - - expect(this.subject('show')).toBe('/foo/bar/-/merge_requests/1?view=parallel#L15-35'); - }); - - it('replaces the current history state', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1', - }); - window.history.replaceState( - { - url: window.location.href, - action: 'show', - }, - document.title, - window.location.href, - ); - - const newState = this.subject('commits'); - - expect(this.spies.history).toHaveBeenCalledWith( - { - url: newState, - action: 'commits', - }, - document.title, - newState, - ); - }); - - it('treats "show" like "notes"', function() { - setLocation({ - pathname: '/foo/bar/-/merge_requests/1/commits', - }); - - expect(this.subject('show')).toBe('/foo/bar/-/merge_requests/1'); - }); - }); - - describe('expandViewContainer', function() { - beforeEach(() => { - $('body').append( - '<div class="content-wrapper"><div class="container-fluid container-limited"></div></div>', - ); - }); - - afterEach(() => { - $('.content-wrapper').remove(); - }); - - it('removes container-limited from containers', function() { - this.class.expandViewContainer(); - - expect($('.content-wrapper')).not.toContainElement('.container-limited'); - }); - - it('does not add container-limited when fluid layout is prefered', function() { - $('.content-wrapper .container-fluid').removeClass('container-limited'); - - this.class.expandViewContainer(false); - - expect($('.content-wrapper')).not.toContainElement('.container-limited'); - }); - - it('does remove container-limited from breadcrumbs', function() { - $('.container-limited').addClass('breadcrumbs'); - this.class.expandViewContainer(); - - expect($('.content-wrapper')).toContainElement('.container-limited'); - }); - }); - - describe('tabShown', function() { - const mainContent = document.createElement('div'); - const tabContent = document.createElement('div'); - - beforeEach(function() { - spyOn(mainContent, 'getBoundingClientRect').and.returnValue({ top: 10 }); - spyOn(tabContent, 'getBoundingClientRect').and.returnValue({ top: 100 }); - spyOn(document, 'querySelector').and.callFake(function(selector) { - return selector === '.content-wrapper' ? mainContent : tabContent; - }); - this.class.currentAction = 'commits'; - }); - - it('calls window scrollTo with options if document has scrollBehavior', function() { - document.documentElement.style.scrollBehavior = ''; - - spyOn(window, 'scrollTo'); - - this.class.tabShown('commits', 'foobar'); - - expect(window.scrollTo.calls.first().args[0]).toEqual({ top: 39, behavior: 'smooth' }); - }); - - it('calls window scrollTo with two args if document does not have scrollBehavior', function() { - spyOnProperty(document.documentElement, 'style', 'get').and.returnValue({}); - - spyOn(window, 'scrollTo'); - - this.class.tabShown('commits', 'foobar'); - - expect(window.scrollTo.calls.first().args).toEqual([0, 39]); - }); - }); -}); diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js deleted file mode 100644 index 9565e3ce546..00000000000 --- a/spec/javascripts/right_sidebar_spec.js +++ /dev/null @@ -1,87 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import '~/commons/bootstrap'; -import axios from '~/lib/utils/axios_utils'; -import Sidebar from '~/right_sidebar'; - -let $aside = null; -let $toggle = null; -let $icon = null; -let $page = null; -let $labelsIcon = null; - -const assertSidebarState = function(state) { - const shouldBeExpanded = state === 'expanded'; - const shouldBeCollapsed = state === 'collapsed'; - expect($aside.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded); - expect($page.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded); - expect($icon.hasClass('fa-angle-double-right')).toBe(shouldBeExpanded); - expect($aside.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed); - expect($page.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed); - expect($icon.hasClass('fa-angle-double-left')).toBe(shouldBeCollapsed); -}; - -describe('RightSidebar', function() { - describe('fixture tests', () => { - const fixtureName = 'issues/open-issue.html'; - preloadFixtures(fixtureName); - loadJSONFixtures('todos/todos.json'); - let mock; - - beforeEach(function() { - loadFixtures(fixtureName); - mock = new MockAdapter(axios); - new Sidebar(); // eslint-disable-line no-new - $aside = $('.right-sidebar'); - $page = $('.layout-page'); - $icon = $aside.find('i'); - $toggle = $aside.find('.js-sidebar-toggle'); - $labelsIcon = $aside.find('.sidebar-collapsed-icon'); - }); - - afterEach(() => { - mock.restore(); - }); - - it('should expand/collapse the sidebar when arrow is clicked', function() { - assertSidebarState('expanded'); - $toggle.click(); - assertSidebarState('collapsed'); - $toggle.click(); - assertSidebarState('expanded'); - }); - - it('should float over the page and when sidebar icons clicked', function() { - $labelsIcon.click(); - assertSidebarState('expanded'); - }); - - it('should collapse when the icon arrow clicked while it is floating on page', function() { - $labelsIcon.click(); - assertSidebarState('expanded'); - $toggle.click(); - assertSidebarState('collapsed'); - }); - - it('should broadcast todo:toggle event when add todo clicked', function(done) { - const todos = getJSONFixture('todos/todos.json'); - mock.onPost(/(.*)\/todos$/).reply(200, todos); - - const todoToggleSpy = spyOnEvent(document, 'todo:toggle'); - - $('.issuable-sidebar-header .js-issuable-todo').click(); - - setTimeout(() => { - expect(todoToggleSpy.calls.count()).toEqual(1); - - done(); - }); - }); - - it('should not hide collapsed icons', () => { - [].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), el => { - expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBeFalsy(); - }); - }); - }); -}); diff --git a/spec/javascripts/shortcuts_spec.js b/spec/javascripts/shortcuts_spec.js deleted file mode 100644 index df7012bb659..00000000000 --- a/spec/javascripts/shortcuts_spec.js +++ /dev/null @@ -1,46 +0,0 @@ -import $ from 'jquery'; -import Shortcuts from '~/behaviors/shortcuts/shortcuts'; - -describe('Shortcuts', () => { - const fixtureName = 'snippets/show.html'; - const createEvent = (type, target) => - $.Event(type, { - target, - }); - - preloadFixtures(fixtureName); - - describe('toggleMarkdownPreview', () => { - beforeEach(() => { - loadFixtures(fixtureName); - - spyOnEvent('.js-new-note-form .js-md-preview-button', 'focus'); - spyOnEvent('.edit-note .js-md-preview-button', 'focus'); - - new Shortcuts(); // eslint-disable-line no-new - }); - - it('focuses preview button in form', () => { - Shortcuts.toggleMarkdownPreview( - createEvent('KeyboardEvent', document.querySelector('.js-new-note-form .js-note-text')), - ); - - expect('focus').toHaveBeenTriggeredOn('.js-new-note-form .js-md-preview-button'); - }); - - it('focues preview button inside edit comment form', done => { - document.querySelector('.js-note-edit').click(); - - setTimeout(() => { - Shortcuts.toggleMarkdownPreview( - createEvent('KeyboardEvent', document.querySelector('.edit-note .js-note-text')), - ); - - expect('focus').not.toHaveBeenTriggeredOn('.js-new-note-form .js-md-preview-button'); - expect('focus').toHaveBeenTriggeredOn('.edit-note .js-md-preview-button'); - - done(); - }); - }); - }); -}); diff --git a/spec/javascripts/user_popovers_spec.js b/spec/javascripts/user_popovers_spec.js deleted file mode 100644 index 6ac22fca2d3..00000000000 --- a/spec/javascripts/user_popovers_spec.js +++ /dev/null @@ -1,95 +0,0 @@ -import initUserPopovers from '~/user_popovers'; -import UsersCache from '~/lib/utils/users_cache'; - -describe('User Popovers', () => { - const fixtureTemplate = 'merge_requests/merge_request_with_mentions.html'; - preloadFixtures(fixtureTemplate); - - const selector = '.js-user-link, .gfm-project_member'; - - const dummyUser = { name: 'root' }; - const dummyUserStatus = { message: 'active' }; - - let popovers; - - const triggerEvent = (eventName, el) => { - const event = new MouseEvent(eventName, { - bubbles: true, - cancelable: true, - view: window, - }); - - el.dispatchEvent(event); - }; - - beforeEach(() => { - loadFixtures(fixtureTemplate); - - const usersCacheSpy = () => Promise.resolve(dummyUser); - spyOn(UsersCache, 'retrieveById').and.callFake(userId => usersCacheSpy(userId)); - - const userStatusCacheSpy = () => Promise.resolve(dummyUserStatus); - spyOn(UsersCache, 'retrieveStatusById').and.callFake(userId => userStatusCacheSpy(userId)); - - popovers = initUserPopovers(document.querySelectorAll(selector)); - }); - - it('initializes a popover for each user link with a user id', () => { - const linksWithUsers = Array.from(document.querySelectorAll(selector)).filter( - ({ dataset }) => dataset.user || dataset.userId, - ); - - expect(linksWithUsers.length).toBe(popovers.length); - }); - - it('does not initialize the user popovers twice for the same element', () => { - const newPopovers = initUserPopovers(document.querySelectorAll(selector)); - const samePopovers = popovers.every((popover, index) => newPopovers[index] === popover); - - expect(samePopovers).toBe(true); - }); - - describe('when user link emits mouseenter event', () => { - let userLink; - - beforeEach(() => { - userLink = document.querySelector(selector); - - triggerEvent('mouseenter', userLink); - }); - - it('removes title attribute from user links', () => { - expect(userLink.getAttribute('title')).toBeFalsy(); - expect(userLink.dataset.originalTitle).toBeFalsy(); - }); - - it('populates popovers with preloaded user data', () => { - const { name, userId, username } = userLink.dataset; - const [firstPopover] = popovers; - - expect(firstPopover.$props.user).toEqual( - jasmine.objectContaining({ - name, - userId, - username, - }), - ); - }); - - it('fetches user info and status from the user cache', () => { - const { userId } = userLink.dataset; - - expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId); - expect(UsersCache.retrieveStatusById).toHaveBeenCalledWith(userId); - }); - }); - - it('removes aria-describedby attribute from the user link on mouseleave', () => { - const userLink = document.querySelector(selector); - - userLink.setAttribute('aria-describedby', 'popover'); - triggerEvent('mouseleave', userLink); - - expect(userLink.getAttribute('aria-describedby')).toBe(null); - }); -}); diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js deleted file mode 100644 index 5dee11b3810..00000000000 --- a/spec/javascripts/zen_mode_spec.js +++ /dev/null @@ -1,106 +0,0 @@ -import $ from 'jquery'; -import Dropzone from 'dropzone'; -import Mousetrap from 'mousetrap'; -import ZenMode from '~/zen_mode'; -import initNotes from '~/init_notes'; - -describe('ZenMode', () => { - let zen; - let dropzoneForElementSpy; - const fixtureName = 'snippets/show.html'; - - preloadFixtures(fixtureName); - - function enterZen() { - $('.notes-form .js-zen-enter').click(); - } - - function exitZen() { - $('.notes-form .js-zen-leave').click(); - } - - function escapeKeydown() { - $('.notes-form textarea').trigger( - $.Event('keydown', { - keyCode: 27, - }), - ); - } - - beforeEach(() => { - loadFixtures(fixtureName); - initNotes(); - - dropzoneForElementSpy = spyOn(Dropzone, 'forElement').and.callFake(() => ({ - enable: () => true, - })); - zen = new ZenMode(); - - // Set this manually because we can't actually scroll the window - zen.scroll_position = 456; - }); - - describe('enabling dropzone', () => { - beforeEach(() => { - enterZen(); - }); - - it('should not call dropzone if element is not dropzone valid', () => { - $('.div-dropzone').addClass('js-invalid-dropzone'); - exitZen(); - - expect(dropzoneForElementSpy.calls.count()).toEqual(0); - }); - - it('should call dropzone if element is dropzone valid', () => { - $('.div-dropzone').removeClass('js-invalid-dropzone'); - exitZen(); - - expect(dropzoneForElementSpy.calls.count()).toEqual(2); - }); - }); - - describe('on enter', () => { - it('pauses Mousetrap', () => { - const mouseTrapPauseSpy = spyOn(Mousetrap, 'pause'); - enterZen(); - - expect(mouseTrapPauseSpy).toHaveBeenCalled(); - }); - - it('removes textarea styling', () => { - $('.notes-form textarea').attr('style', 'height: 400px'); - enterZen(); - - expect($('.notes-form textarea')).not.toHaveAttr('style'); - }); - }); - - describe('in use', () => { - beforeEach(enterZen); - - it('exits on Escape', () => { - escapeKeydown(); - - expect($('.notes-form .zen-backdrop')).not.toHaveClass('fullscreen'); - }); - }); - - describe('on exit', () => { - beforeEach(enterZen); - - it('unpauses Mousetrap', () => { - const mouseTrapUnpauseSpy = spyOn(Mousetrap, 'unpause'); - exitZen(); - - expect(mouseTrapUnpauseSpy).toHaveBeenCalled(); - }); - - it('restores the scroll position', () => { - spyOn(zen, 'scrollTo'); - exitZen(); - - expect(zen.scrollTo).toHaveBeenCalled(); - }); - }); -}); |