diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 15:07:52 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 15:07:52 +0300 |
commit | 374cf04cf2a496344e0e27d8ddf740f7a543f7af (patch) | |
tree | fb8ecdec56537bfe48551fa333715d5f38c41561 /spec/javascripts | |
parent | 1f5a2543e4daf21dd98d8ff0514781c403445c81 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/javascripts')
-rw-r--r-- | spec/javascripts/gl_dropdown_spec.js | 341 | ||||
-rw-r--r-- | spec/javascripts/importer_status_spec.js | 138 | ||||
-rw-r--r-- | spec/javascripts/merge_request_spec.js | 187 | ||||
-rw-r--r-- | spec/javascripts/mini_pipeline_graph_dropdown_spec.js | 106 | ||||
-rw-r--r-- | spec/javascripts/pager_spec.js | 162 | ||||
-rw-r--r-- | spec/javascripts/persistent_user_callout_spec.js | 175 | ||||
-rw-r--r-- | spec/javascripts/read_more_spec.js | 23 | ||||
-rw-r--r-- | spec/javascripts/signin_tabs_memoizer_spec.js | 216 | ||||
-rw-r--r-- | spec/javascripts/todos_spec.js | 108 |
9 files changed, 0 insertions, 1456 deletions
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js deleted file mode 100644 index 06f76c581f2..00000000000 --- a/spec/javascripts/gl_dropdown_spec.js +++ /dev/null @@ -1,341 +0,0 @@ -/* eslint-disable no-param-reassign */ - -import $ from 'jquery'; -import GLDropdown from '~/gl_dropdown'; -import '~/lib/utils/common_utils'; - -describe('glDropdown', function describeDropdown() { - preloadFixtures('static/gl_dropdown.html'); - loadJSONFixtures('static/projects.json'); - - const NON_SELECTABLE_CLASSES = - '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item'; - const SEARCH_INPUT_SELECTOR = '.dropdown-input-field'; - const ITEM_SELECTOR = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`; - const FOCUSED_ITEM_SELECTOR = `${ITEM_SELECTOR} a.is-focused`; - - const ARROW_KEYS = { - DOWN: 40, - UP: 38, - ENTER: 13, - ESC: 27, - }; - - let remoteCallback; - - const navigateWithKeys = function navigateWithKeys(direction, steps, cb, i) { - i = i || 0; - if (!i) direction = direction.toUpperCase(); - $('body').trigger({ - type: 'keydown', - which: ARROW_KEYS[direction], - keyCode: ARROW_KEYS[direction], - }); - i += 1; - if (i <= steps) { - navigateWithKeys(direction, steps, cb, i); - } else { - cb(); - } - }; - - const remoteMock = function remoteMock(data, term, callback) { - remoteCallback = callback.bind({}, data); - }; - - function initDropDown(hasRemote, isFilterable, extraOpts = {}) { - const options = { - selectable: true, - filterable: isFilterable, - data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData, - search: { - fields: ['name'], - }, - text: project => project.name_with_namespace || project.name, - id: project => project.id, - ...extraOpts, - }; - this.dropdownButtonElement = $( - '#js-project-dropdown', - this.dropdownContainerElement, - ).glDropdown(options); - } - - beforeEach(() => { - loadFixtures('static/gl_dropdown.html'); - this.dropdownContainerElement = $('.dropdown.inline'); - this.$dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement); - this.projectsData = getJSONFixture('static/projects.json'); - }); - - afterEach(() => { - $('body').off('keydown'); - this.dropdownContainerElement.off('keyup'); - }); - - it('should open on click', () => { - initDropDown.call(this, false); - - expect(this.dropdownContainerElement).not.toHaveClass('show'); - this.dropdownButtonElement.click(); - - expect(this.dropdownContainerElement).toHaveClass('show'); - }); - - it('escapes HTML as text', () => { - this.projectsData[0].name_with_namespace = '<script>alert("testing");</script>'; - - initDropDown.call(this, false); - - this.dropdownButtonElement.click(); - - expect($('.dropdown-content li:first-child').text()).toBe('<script>alert("testing");</script>'); - }); - - it('should output HTML when highlighting', () => { - this.projectsData[0].name_with_namespace = 'testing'; - $('.dropdown-input .dropdown-input-field').val('test'); - - initDropDown.call(this, false, true, { - highlight: true, - }); - - this.dropdownButtonElement.click(); - - expect($('.dropdown-content li:first-child').text()).toBe('testing'); - - expect($('.dropdown-content li:first-child a').html()).toBe( - '<b>t</b><b>e</b><b>s</b><b>t</b>ing', - ); - }); - - describe('that is open', () => { - beforeEach(() => { - initDropDown.call(this, false, false); - this.dropdownButtonElement.click(); - }); - - it('should select a following item on DOWN keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0); - const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 1)) + 0; - navigateWithKeys('down', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); - expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement)).toHaveClass( - 'is-focused', - ); - }); - }); - - it('should select a previous item on UP keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0); - navigateWithKeys('down', this.projectsData.length - 1, () => { - expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); - const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 2)) + 0; - navigateWithKeys('up', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); - expect( - $( - `${ITEM_SELECTOR}:eq(${this.projectsData.length - 2 - randomIndex}) a`, - this.$dropdownMenuElement, - ), - ).toHaveClass('is-focused'); - }); - }); - }); - - it('should click the selected item on ENTER keypress', () => { - expect(this.dropdownContainerElement).toHaveClass('show'); - const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 1)) + 0; - navigateWithKeys('down', randomIndex, () => { - const visitUrl = spyOnDependency(GLDropdown, 'visitUrl').and.stub(); - navigateWithKeys('enter', null, () => { - expect(this.dropdownContainerElement).not.toHaveClass('show'); - const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement); - - expect(link).toHaveClass('is-active'); - const linkedLocation = link.attr('href'); - if (linkedLocation && linkedLocation !== '#') { - expect(visitUrl).toHaveBeenCalledWith(linkedLocation); - } - }); - }); - }); - - it('should close on ESC keypress', () => { - expect(this.dropdownContainerElement).toHaveClass('show'); - this.dropdownContainerElement.trigger({ - type: 'keyup', - which: ARROW_KEYS.ESC, - keyCode: ARROW_KEYS.ESC, - }); - - expect(this.dropdownContainerElement).not.toHaveClass('show'); - }); - }); - - describe('opened and waiting for a remote callback', () => { - beforeEach(() => { - initDropDown.call(this, true, true); - this.dropdownButtonElement.click(); - }); - - it('should show loading indicator while search results are being fetched by backend', () => { - const dropdownMenu = document.querySelector('.dropdown-menu'); - - expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1); - remoteCallback(); - - expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1); - }); - - it('should not focus search input while remote task is not complete', () => { - expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR)); - remoteCallback(); - - expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); - }); - - it('should focus search input after remote task is complete', () => { - remoteCallback(); - - expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); - }); - - it('should focus on input when opening for the second time after transition', () => { - remoteCallback(); - this.dropdownContainerElement.trigger({ - type: 'keyup', - which: ARROW_KEYS.ESC, - keyCode: ARROW_KEYS.ESC, - }); - this.dropdownButtonElement.click(); - this.dropdownContainerElement.trigger('transitionend'); - - expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); - }); - }); - - describe('input focus with array data', () => { - it('should focus input when passing array data to drop down', () => { - initDropDown.call(this, false, true); - this.dropdownButtonElement.click(); - this.dropdownContainerElement.trigger('transitionend'); - - expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); - }); - }); - - it('should still have input value on close and restore', () => { - const $searchInput = $(SEARCH_INPUT_SELECTOR); - initDropDown.call(this, false, true); - $searchInput - .trigger('focus') - .val('g') - .trigger('input'); - - expect($searchInput.val()).toEqual('g'); - this.dropdownButtonElement.trigger('hidden.bs.dropdown'); - $searchInput.trigger('blur').trigger('focus'); - - expect($searchInput.val()).toEqual('g'); - }); - - describe('renderItem', () => { - function dropdownWithOptions(options) { - const $dropdownDiv = $('<div />'); - - $dropdownDiv.glDropdown(options); - - return $dropdownDiv.data('glDropdown'); - } - - function basicDropdown() { - return dropdownWithOptions({}); - } - - describe('without selected value', () => { - let dropdown; - - beforeEach(() => { - dropdown = basicDropdown(); - }); - - it('marks items without ID as active', () => { - const dummyData = {}; - - const html = dropdown.renderItem(dummyData, null, null); - - const link = html.querySelector('a'); - - expect(link).toHaveClass('is-active'); - }); - - it('does not mark items with ID as active', () => { - const dummyData = { - id: 'ea', - }; - - const html = dropdown.renderItem(dummyData, null, null); - - const link = html.querySelector('a'); - - expect(link).not.toHaveClass('is-active'); - }); - }); - - it('should return an empty .separator li when when appropriate', () => { - const dropdown = basicDropdown(); - const sep = { type: 'separator' }; - const li = dropdown.renderItem(sep); - - expect(li).toHaveClass('separator'); - expect(li.childNodes.length).toEqual(0); - }); - - it('should return an empty .divider li when when appropriate', () => { - const dropdown = basicDropdown(); - const div = { type: 'divider' }; - const li = dropdown.renderItem(div); - - expect(li).toHaveClass('divider'); - expect(li.childNodes.length).toEqual(0); - }); - - it('should return a .dropdown-header li with the correct content when when appropriate', () => { - const dropdown = basicDropdown(); - const text = 'My Header'; - const header = { type: 'header', content: text }; - const li = dropdown.renderItem(header); - - expect(li).toHaveClass('dropdown-header'); - expect(li.childNodes.length).toEqual(1); - expect(li.textContent).toEqual(text); - }); - }); - - it('should keep selected item after selecting a second time', () => { - const options = { - isSelectable(item, $el) { - return !$el.hasClass('is-active'); - }, - toggleLabel(item) { - return item && item.id; - }, - }; - initDropDown.call(this, false, false, options); - const $item = $(`${ITEM_SELECTOR}:first() a`, this.$dropdownMenuElement); - - // select item the first time - this.dropdownButtonElement.click(); - $item.click(); - - expect($item).toHaveClass('is-active'); - // select item the second time - this.dropdownButtonElement.click(); - $item.click(); - - expect($item).toHaveClass('is-active'); - - expect($('.dropdown-toggle-text')).toHaveText(this.projectsData[0].id.toString()); - }); -}); diff --git a/spec/javascripts/importer_status_spec.js b/spec/javascripts/importer_status_spec.js deleted file mode 100644 index 90835e1cc21..00000000000 --- a/spec/javascripts/importer_status_spec.js +++ /dev/null @@ -1,138 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import { ImporterStatus } from '~/importer_status'; -import axios from '~/lib/utils/axios_utils'; - -describe('Importer Status', () => { - let instance; - let mock; - - beforeEach(() => { - mock = new MockAdapter(axios); - }); - - afterEach(() => { - mock.restore(); - }); - - describe('addToImport', () => { - const importUrl = '/import_url'; - - beforeEach(() => { - setFixtures(` - <tr id="repo_123"> - <td class="import-target"></td> - <td class="import-actions job-status"> - <button name="button" type="submit" class="btn btn-import js-add-to-import"> - </button> - </td> - </tr> - `); - spyOn(ImporterStatus.prototype, 'initStatusPage').and.callFake(() => {}); - spyOn(ImporterStatus.prototype, 'setAutoUpdate').and.callFake(() => {}); - instance = new ImporterStatus({ - jobsUrl: '', - importUrl, - }); - }); - - it('sets table row to active after post request', done => { - mock.onPost(importUrl).reply(200, { - id: 1, - full_path: '/full_path', - }); - - instance - .addToImport({ - currentTarget: document.querySelector('.js-add-to-import'), - }) - .then(() => { - expect(document.querySelector('tr').classList.contains('table-active')).toEqual(true); - done(); - }) - .catch(done.fail); - }); - - it('shows error message after failed POST request', done => { - appendSetFixtures('<div class="flash-container"></div>'); - - mock.onPost(importUrl).reply(422, { - errors: 'You forgot your lunch', - }); - - instance - .addToImport({ - currentTarget: document.querySelector('.js-add-to-import'), - }) - .then(() => { - const flashMessage = document.querySelector('.flash-text'); - - expect(flashMessage.textContent.trim()).toEqual( - 'An error occurred while importing project: You forgot your lunch', - ); - done(); - }) - .catch(done.fail); - }); - }); - - describe('autoUpdate', () => { - const jobsUrl = '/jobs_url'; - - beforeEach(() => { - const div = document.createElement('div'); - div.innerHTML = ` - <div id="project_1"> - <div class="job-status"> - </div> - </div> - `; - - document.body.appendChild(div); - - spyOn(ImporterStatus.prototype, 'initStatusPage').and.callFake(() => {}); - spyOn(ImporterStatus.prototype, 'setAutoUpdate').and.callFake(() => {}); - instance = new ImporterStatus({ - jobsUrl, - }); - }); - - function setupMock(importStatus) { - mock.onGet(jobsUrl).reply(200, [ - { - id: 1, - import_status: importStatus, - }, - ]); - } - - function expectJobStatus(done, status) { - instance - .autoUpdate() - .then(() => { - expect(document.querySelector('#project_1').innerText.trim()).toEqual(status); - done(); - }) - .catch(done.fail); - } - - it('sets the job status to done', done => { - setupMock('finished'); - expectJobStatus(done, 'Done'); - }); - - it('sets the job status to scheduled', done => { - setupMock('scheduled'); - expectJobStatus(done, 'Scheduled'); - }); - - it('sets the job status to started', done => { - setupMock('started'); - expectJobStatus(done, 'Started'); - }); - - it('sets the job status to custom status', done => { - setupMock('custom status'); - expectJobStatus(done, 'custom status'); - }); - }); -}); diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js deleted file mode 100644 index b6173b9b171..00000000000 --- a/spec/javascripts/merge_request_spec.js +++ /dev/null @@ -1,187 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import MergeRequest from '~/merge_request'; -import CloseReopenReportToggle from '~/close_reopen_report_toggle'; -import IssuablesHelper from '~/helpers/issuables_helper'; - -describe('MergeRequest', function() { - describe('task lists', function() { - let mock; - - preloadFixtures('merge_requests/merge_request_with_task_list.html'); - beforeEach(function() { - loadFixtures('merge_requests/merge_request_with_task_list.html'); - - spyOn(axios, 'patch').and.callThrough(); - mock = new MockAdapter(axios); - - mock - .onPatch(`${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`) - .reply(200, {}); - - this.merge = new MergeRequest(); - return this.merge; - }); - - afterEach(() => { - mock.restore(); - }); - - it('modifies the Markdown field', done => { - spyOn($, 'ajax').and.stub(); - const changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', true, true); - $('input[type=checkbox]') - .first() - .attr('checked', true)[0] - .dispatchEvent(changeEvent); - setTimeout(() => { - expect($('.js-task-list-field').val()).toBe( - '- [x] Task List Item\n- [ ] \n- [ ] Task List Item 2\n', - ); - done(); - }); - }); - - it('ensure that task with only spaces does not get checked incorrectly', done => { - // fixed in 'deckar01-task_list', '2.2.1' gem - spyOn($, 'ajax').and.stub(); - const changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', true, true); - $('input[type=checkbox]') - .last() - .attr('checked', true)[0] - .dispatchEvent(changeEvent); - setTimeout(() => { - expect($('.js-task-list-field').val()).toBe( - '- [ ] Task List Item\n- [ ] \n- [x] Task List Item 2\n', - ); - done(); - }); - }); - - describe('tasklist', () => { - const lineNumber = 8; - const lineSource = '- [ ] item 8'; - const index = 3; - const checked = true; - - it('submits an ajax request on tasklist:changed', done => { - $('.js-task-list-field').trigger({ - type: 'tasklist:changed', - detail: { lineNumber, lineSource, index, checked }, - }); - - setTimeout(() => { - expect(axios.patch).toHaveBeenCalledWith( - `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`, - { - merge_request: { - description: '- [ ] Task List Item\n- [ ] \n- [ ] Task List Item 2\n', - lock_version: 0, - update_task: { line_number: lineNumber, line_source: lineSource, index, checked }, - }, - }, - ); - - done(); - }); - }); - - // https://gitlab.com/gitlab-org/gitlab/issues/34861 - // eslint-disable-next-line jasmine/no-disabled-tests - xit('shows an error notification when tasklist update failed', done => { - mock - .onPatch( - `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/-/merge_requests/1.json`, - ) - .reply(409, {}); - - $('.js-task-list-field').trigger({ - type: 'tasklist:changed', - detail: { lineNumber, lineSource, index, checked }, - }); - - setTimeout(() => { - expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( - 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.', - ); - - done(); - }); - }); - }); - }); - - describe('class constructor', () => { - beforeEach(() => { - spyOn($, 'ajax').and.stub(); - }); - - it('calls .initCloseReopenReport', () => { - spyOn(IssuablesHelper, 'initCloseReopenReport'); - - new MergeRequest(); // eslint-disable-line no-new - - expect(IssuablesHelper.initCloseReopenReport).toHaveBeenCalled(); - }); - - it('calls .initDroplab', () => { - const container = jasmine.createSpyObj('container', ['querySelector']); - const dropdownTrigger = {}; - const dropdownList = {}; - const button = {}; - - spyOn(CloseReopenReportToggle.prototype, 'initDroplab'); - spyOn(document, 'querySelector').and.returnValue(container); - container.querySelector.and.returnValues(dropdownTrigger, dropdownList, button); - - new MergeRequest(); // eslint-disable-line no-new - - expect(document.querySelector).toHaveBeenCalledWith('.js-issuable-close-dropdown'); - expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-toggle'); - expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-menu'); - expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-button'); - expect(CloseReopenReportToggle.prototype.initDroplab).toHaveBeenCalled(); - }); - }); - - describe('hideCloseButton', () => { - describe('merge request of another user', () => { - beforeEach(() => { - loadFixtures('merge_requests/merge_request_with_task_list.html'); - this.el = document.querySelector('.js-issuable-actions'); - new MergeRequest(); // eslint-disable-line no-new - MergeRequest.hideCloseButton(); - }); - - it('hides the dropdown close item and selects the next item', () => { - const closeItem = this.el.querySelector('li.close-item'); - const smallCloseItem = this.el.querySelector('.js-close-item'); - const reportItem = this.el.querySelector('li.report-item'); - - expect(closeItem).toHaveClass('hidden'); - expect(smallCloseItem).toHaveClass('hidden'); - expect(reportItem).toHaveClass('droplab-item-selected'); - expect(reportItem).not.toHaveClass('hidden'); - }); - }); - - describe('merge request of current_user', () => { - beforeEach(() => { - loadFixtures('merge_requests/merge_request_of_current_user.html'); - this.el = document.querySelector('.js-issuable-actions'); - MergeRequest.hideCloseButton(); - }); - - it('hides the close button', () => { - const closeButton = this.el.querySelector('.btn-close'); - const smallCloseItem = this.el.querySelector('.js-close-item'); - - expect(closeButton).toHaveClass('hidden'); - expect(smallCloseItem).toHaveClass('hidden'); - }); - }); - }); -}); diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js deleted file mode 100644 index aa4a376caf7..00000000000 --- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js +++ /dev/null @@ -1,106 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; -import timeoutPromise from './helpers/set_timeout_promise_helper'; - -describe('Mini Pipeline Graph Dropdown', () => { - preloadFixtures('static/mini_dropdown_graph.html'); - - beforeEach(() => { - loadFixtures('static/mini_dropdown_graph.html'); - }); - - describe('When is initialized', () => { - it('should initialize without errors when no options are given', () => { - const miniPipelineGraph = new MiniPipelineGraph(); - - expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container'); - }); - - it('should set the container as the given prop', () => { - const container = '.foo'; - - const miniPipelineGraph = new MiniPipelineGraph({ container }); - - expect(miniPipelineGraph.container).toEqual(container); - }); - }); - - describe('When dropdown is clicked', () => { - let mock; - - beforeEach(() => { - mock = new MockAdapter(axios); - }); - - afterEach(() => { - mock.restore(); - }); - - it('should call getBuildsList', () => { - const getBuildsListSpy = spyOn(MiniPipelineGraph.prototype, 'getBuildsList').and.callFake( - function() {}, - ); - - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - - document.querySelector('.js-builds-dropdown-button').click(); - - expect(getBuildsListSpy).toHaveBeenCalled(); - }); - - it('should make a request to the endpoint provided in the html', () => { - const ajaxSpy = spyOn(axios, 'get').and.callThrough(); - - mock.onGet('foobar').reply(200, { - html: '', - }); - - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - - document.querySelector('.js-builds-dropdown-button').click(); - - expect(ajaxSpy.calls.allArgs()[0][0]).toEqual('foobar'); - }); - - it('should not close when user uses cmd/ctrl + click', done => { - mock.onGet('foobar').reply(200, { - html: `<li> - <a class="mini-pipeline-graph-dropdown-item" href="#"> - <span class="ci-status-icon ci-status-icon-failed"></span> - <span class="ci-build-text">build</span> - </a> - <a class="ci-action-icon-wrapper js-ci-action-icon" href="#"></a> - </li>`, - }); - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - - document.querySelector('.js-builds-dropdown-button').click(); - - timeoutPromise() - .then(() => { - document.querySelector('a.mini-pipeline-graph-dropdown-item').click(); - }) - .then(timeoutPromise) - .then(() => { - expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true); - }) - .then(done) - .catch(done.fail); - }); - - it('should close the dropdown when request returns an error', done => { - mock.onGet('foobar').networkError(); - - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - - document.querySelector('.js-builds-dropdown-button').click(); - - setTimeout(() => { - expect($('.js-builds-dropdown-tests .dropdown').hasClass('open')).toEqual(false); - done(); - }); - }); - }); -}); diff --git a/spec/javascripts/pager_spec.js b/spec/javascripts/pager_spec.js deleted file mode 100644 index c95a8400c6c..00000000000 --- a/spec/javascripts/pager_spec.js +++ /dev/null @@ -1,162 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import Pager from '~/pager'; - -describe('pager', () => { - let axiosMock; - - beforeEach(() => { - axiosMock = new MockAdapter(axios); - }); - - afterEach(() => { - axiosMock.restore(); - }); - - describe('init', () => { - const originalHref = window.location.href; - - beforeEach(() => { - setFixtures('<div class="content_list"></div><div class="loading"></div>'); - spyOn($.fn, 'endlessScroll').and.stub(); - }); - - afterEach(() => { - window.history.replaceState({}, null, originalHref); - }); - - it('should use data-href attribute from list element', () => { - const href = `${gl.TEST_HOST}/some_list.json`; - setFixtures(`<div class="content_list" data-href="${href}"></div>`); - Pager.init(); - - expect(Pager.url).toBe(href); - }); - - it('should use current url if data-href attribute not provided', () => { - const href = `${gl.TEST_HOST}/some_list`; - spyOnDependency(Pager, 'removeParams').and.returnValue(href); - Pager.init(); - - expect(Pager.url).toBe(href); - }); - - it('should get initial offset from query parameter', () => { - window.history.replaceState({}, null, '?offset=100'); - Pager.init(); - - expect(Pager.offset).toBe(100); - }); - - it('keeps extra query parameters from url', () => { - window.history.replaceState({}, null, '?filter=test&offset=100'); - const href = `${gl.TEST_HOST}/some_list?filter=test`; - const removeParams = spyOnDependency(Pager, 'removeParams').and.returnValue(href); - Pager.init(); - - expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']); - expect(Pager.url).toEqual(href); - }); - }); - - describe('getOld', () => { - const urlRegex = /(.*)some_list(.*)$/; - - function mockSuccess(count = 0) { - axiosMock.onGet(urlRegex).reply(200, { - count, - html: '', - }); - } - - function mockError() { - axiosMock.onGet(urlRegex).networkError(); - } - - beforeEach(() => { - setFixtures( - '<div class="content_list" data-href="/some_list"></div><div class="loading"></div>', - ); - spyOn(axios, 'get').and.callThrough(); - - Pager.init(); - }); - - it('shows loader while loading next page', done => { - mockSuccess(); - - spyOn(Pager.loading, 'show'); - Pager.getOld(); - - setTimeout(() => { - expect(Pager.loading.show).toHaveBeenCalled(); - - done(); - }); - }); - - it('hides loader on success', done => { - mockSuccess(); - - spyOn(Pager.loading, 'hide'); - Pager.getOld(); - - setTimeout(() => { - expect(Pager.loading.hide).toHaveBeenCalled(); - - done(); - }); - }); - - it('hides loader on error', done => { - mockError(); - - spyOn(Pager.loading, 'hide'); - Pager.getOld(); - - setTimeout(() => { - expect(Pager.loading.hide).toHaveBeenCalled(); - - done(); - }); - }); - - it('sends request to url with offset and limit params', done => { - Pager.offset = 100; - Pager.limit = 20; - Pager.getOld(); - - setTimeout(() => { - const [url, params] = axios.get.calls.argsFor(0); - - expect(params).toEqual({ - params: { - limit: 20, - offset: 100, - }, - }); - - expect(url).toBe('/some_list'); - - done(); - }); - }); - - it('disables if return count is less than limit', done => { - Pager.offset = 0; - Pager.limit = 20; - - mockSuccess(1); - spyOn(Pager.loading, 'hide'); - Pager.getOld(); - - setTimeout(() => { - expect(Pager.loading.hide).toHaveBeenCalled(); - expect(Pager.disable).toBe(true); - - done(); - }); - }); - }); -}); diff --git a/spec/javascripts/persistent_user_callout_spec.js b/spec/javascripts/persistent_user_callout_spec.js deleted file mode 100644 index d4cb92cacfd..00000000000 --- a/spec/javascripts/persistent_user_callout_spec.js +++ /dev/null @@ -1,175 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper'; -import axios from '~/lib/utils/axios_utils'; -import PersistentUserCallout from '~/persistent_user_callout'; - -describe('PersistentUserCallout', () => { - const dismissEndpoint = '/dismiss'; - const featureName = 'feature'; - - function createFixture() { - const fixture = document.createElement('div'); - fixture.innerHTML = ` - <div - class="container" - data-dismiss-endpoint="${dismissEndpoint}" - data-feature-id="${featureName}" - > - <button type="button" class="js-close"></button> - </div> - `; - - return fixture; - } - - function createDeferredLinkFixture() { - const fixture = document.createElement('div'); - fixture.innerHTML = ` - <div - class="container" - data-dismiss-endpoint="${dismissEndpoint}" - data-feature-id="${featureName}" - data-defer-links="true" - > - <button type="button" class="js-close"></button> - <a href="/somewhere-pleasant" target="_blank" class="deferred-link">A link</a> - <a href="/somewhere-else" target="_blank" class="normal-link">Another link</a> - </div> - `; - - return fixture; - } - - describe('dismiss', () => { - let button; - let mockAxios; - let persistentUserCallout; - - beforeEach(() => { - const fixture = createFixture(); - const container = fixture.querySelector('.container'); - button = fixture.querySelector('.js-close'); - mockAxios = new MockAdapter(axios); - persistentUserCallout = new PersistentUserCallout(container); - spyOn(persistentUserCallout.container, 'remove'); - }); - - afterEach(() => { - mockAxios.restore(); - }); - - it('POSTs endpoint and removes container when clicking close', done => { - mockAxios.onPost(dismissEndpoint).replyOnce(200); - - button.click(); - - setTimeoutPromise() - .then(() => { - expect(persistentUserCallout.container.remove).toHaveBeenCalled(); - expect(mockAxios.history.post[0].data).toBe( - JSON.stringify({ feature_name: featureName }), - ); - }) - .then(done) - .catch(done.fail); - }); - - it('invokes Flash when the dismiss request fails', done => { - const Flash = spyOnDependency(PersistentUserCallout, 'Flash'); - mockAxios.onPost(dismissEndpoint).replyOnce(500); - - button.click(); - - setTimeoutPromise() - .then(() => { - expect(persistentUserCallout.container.remove).not.toHaveBeenCalled(); - expect(Flash).toHaveBeenCalledWith( - 'An error occurred while dismissing the alert. Refresh the page and try again.', - ); - }) - .then(done) - .catch(done.fail); - }); - }); - - describe('deferred links', () => { - let button; - let deferredLink; - let normalLink; - let mockAxios; - let persistentUserCallout; - let windowSpy; - - beforeEach(() => { - const fixture = createDeferredLinkFixture(); - const container = fixture.querySelector('.container'); - button = fixture.querySelector('.js-close'); - deferredLink = fixture.querySelector('.deferred-link'); - normalLink = fixture.querySelector('.normal-link'); - mockAxios = new MockAdapter(axios); - persistentUserCallout = new PersistentUserCallout(container); - spyOn(persistentUserCallout.container, 'remove'); - windowSpy = spyOn(window, 'open').and.callFake(() => {}); - }); - - afterEach(() => { - mockAxios.restore(); - }); - - it('defers loading of a link until callout is dismissed', done => { - const { href, target } = deferredLink; - mockAxios.onPost(dismissEndpoint).replyOnce(200); - - deferredLink.click(); - - setTimeoutPromise() - .then(() => { - expect(windowSpy).toHaveBeenCalledWith(href, target); - expect(persistentUserCallout.container.remove).toHaveBeenCalled(); - expect(mockAxios.history.post[0].data).toBe( - JSON.stringify({ feature_name: featureName }), - ); - }) - .then(done) - .catch(done.fail); - }); - - it('does not dismiss callout on non-deferred links', done => { - normalLink.click(); - - setTimeoutPromise() - .then(() => { - expect(windowSpy).not.toHaveBeenCalled(); - expect(persistentUserCallout.container.remove).not.toHaveBeenCalled(); - }) - .then(done) - .catch(done.fail); - }); - - it('does not follow link when notification is closed', done => { - mockAxios.onPost(dismissEndpoint).replyOnce(200); - - button.click(); - - setTimeoutPromise() - .then(() => { - expect(windowSpy).not.toHaveBeenCalled(); - expect(persistentUserCallout.container.remove).toHaveBeenCalled(); - }) - .then(done) - .catch(done.fail); - }); - }); - - describe('factory', () => { - it('returns an instance of PersistentUserCallout with the provided container property', () => { - const fixture = createFixture(); - - expect(PersistentUserCallout.factory(fixture) instanceof PersistentUserCallout).toBe(true); - }); - - it('returns undefined if container is falsey', () => { - expect(PersistentUserCallout.factory()).toBe(undefined); - }); - }); -}); diff --git a/spec/javascripts/read_more_spec.js b/spec/javascripts/read_more_spec.js deleted file mode 100644 index d1d01272403..00000000000 --- a/spec/javascripts/read_more_spec.js +++ /dev/null @@ -1,23 +0,0 @@ -import initReadMore from '~/read_more'; - -describe('Read more click-to-expand functionality', () => { - const fixtureName = 'projects/overview.html'; - - preloadFixtures(fixtureName); - - beforeEach(() => { - loadFixtures(fixtureName); - }); - - describe('expands target element', () => { - it('adds "is-expanded" class to target element', () => { - const target = document.querySelector('.read-more-container'); - const trigger = document.querySelector('.js-read-more-trigger'); - initReadMore(); - - trigger.click(); - - expect(target.classList.contains('is-expanded')).toEqual(true); - }); - }); -}); diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js deleted file mode 100644 index 966ae55ce14..00000000000 --- a/spec/javascripts/signin_tabs_memoizer_spec.js +++ /dev/null @@ -1,216 +0,0 @@ -import AccessorUtilities from '~/lib/utils/accessor'; -import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; -import trackData from '~/pages/sessions/new/index'; -import Tracking from '~/tracking'; - -describe('SigninTabsMemoizer', () => { - const fixtureTemplate = 'static/signin_tabs.html'; - const tabSelector = 'ul.new-session-tabs'; - const currentTabKey = 'current_signin_tab'; - let memo; - - function createMemoizer() { - memo = new SigninTabsMemoizer({ - currentTabKey, - tabSelector, - }); - return memo; - } - - preloadFixtures(fixtureTemplate); - - beforeEach(() => { - loadFixtures(fixtureTemplate); - - spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.returnValue(true); - }); - - it('does nothing if no tab was previously selected', () => { - createMemoizer(); - - expect(document.querySelector(`${tabSelector} > li.active a`).getAttribute('href')).toEqual( - '#ldap', - ); - }); - - it('shows last selected tab on boot', () => { - createMemoizer().saveData('#ldap'); - const fakeTab = { - click: () => {}, - }; - spyOn(document, 'querySelector').and.returnValue(fakeTab); - spyOn(fakeTab, 'click'); - - memo.bootstrap(); - - // verify that triggers click on the last selected tab - expect(document.querySelector).toHaveBeenCalledWith(`${tabSelector} a[href="#ldap"]`); - expect(fakeTab.click).toHaveBeenCalled(); - }); - - it('clicks the first tab if value in local storage is bad', () => { - createMemoizer().saveData('#bogus'); - const fakeTab = { - click: () => {}, - }; - spyOn(document, 'querySelector').and.callFake(selector => - selector === `${tabSelector} a[href="#bogus"]` ? null : fakeTab, - ); - spyOn(fakeTab, 'click'); - - memo.bootstrap(); - - // verify that triggers click on stored selector and fallback - expect(document.querySelector.calls.allArgs()).toEqual([ - ['ul.new-session-tabs a[href="#bogus"]'], - ['ul.new-session-tabs a'], - ]); - - expect(fakeTab.click).toHaveBeenCalled(); - }); - - it('saves last selected tab on change', () => { - createMemoizer(); - - document.querySelector('a[href="#login-pane"]').click(); - - expect(memo.readData()).toEqual('#login-pane'); - }); - - it('overrides last selected tab with hash tag when given', () => { - window.location.hash = '#ldap'; - createMemoizer(); - - expect(memo.readData()).toEqual('#ldap'); - }); - - describe('class constructor', () => { - beforeEach(() => { - memo = createMemoizer(); - }); - - it('should set .isLocalStorageAvailable', () => { - expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled(); - expect(memo.isLocalStorageAvailable).toBe(true); - }); - }); - - describe('trackData', () => { - beforeEach(() => { - spyOn(Tracking, 'event'); - }); - - describe('with tracking data', () => { - beforeEach(() => { - gon.tracking_data = { - category: 'Growth::Acquisition::Experiment::SignUpFlow', - action: 'start', - label: 'uuid', - property: 'control_group', - }; - trackData(); - }); - - it('should track data when the "click" event of the register tab is triggered', () => { - document.querySelector('a[href="#register-pane"]').click(); - - expect(Tracking.event).toHaveBeenCalledWith( - 'Growth::Acquisition::Experiment::SignUpFlow', - 'start', - { - label: 'uuid', - property: 'control_group', - }, - ); - }); - }); - - describe('without tracking data', () => { - beforeEach(() => { - gon.tracking_data = undefined; - trackData(); - }); - - it('should not track data when the "click" event of the register tab is triggered', () => { - document.querySelector('a[href="#register-pane"]').click(); - - expect(Tracking.event).not.toHaveBeenCalled(); - }); - }); - }); - - describe('saveData', () => { - beforeEach(() => { - memo = { - currentTabKey, - }; - - spyOn(localStorage, 'setItem'); - }); - - describe('if .isLocalStorageAvailable is `false`', () => { - beforeEach(function() { - memo.isLocalStorageAvailable = false; - - SigninTabsMemoizer.prototype.saveData.call(memo); - }); - - it('should not call .setItem', () => { - expect(localStorage.setItem).not.toHaveBeenCalled(); - }); - }); - - describe('if .isLocalStorageAvailable is `true`', () => { - const value = 'value'; - - beforeEach(function() { - memo.isLocalStorageAvailable = true; - - SigninTabsMemoizer.prototype.saveData.call(memo, value); - }); - - it('should call .setItem', () => { - expect(localStorage.setItem).toHaveBeenCalledWith(currentTabKey, value); - }); - }); - }); - - describe('readData', () => { - const itemValue = 'itemValue'; - let readData; - - beforeEach(() => { - memo = { - currentTabKey, - }; - - spyOn(localStorage, 'getItem').and.returnValue(itemValue); - }); - - describe('if .isLocalStorageAvailable is `false`', () => { - beforeEach(function() { - memo.isLocalStorageAvailable = false; - - readData = SigninTabsMemoizer.prototype.readData.call(memo); - }); - - it('should not call .getItem and should return `null`', () => { - expect(localStorage.getItem).not.toHaveBeenCalled(); - expect(readData).toBe(null); - }); - }); - - describe('if .isLocalStorageAvailable is `true`', () => { - beforeEach(function() { - memo.isLocalStorageAvailable = true; - - readData = SigninTabsMemoizer.prototype.readData.call(memo); - }); - - it('should call .getItem and return the localStorage value', () => { - expect(window.localStorage.getItem).toHaveBeenCalledWith(currentTabKey); - expect(readData).toBe(itemValue); - }); - }); - }); -}); diff --git a/spec/javascripts/todos_spec.js b/spec/javascripts/todos_spec.js deleted file mode 100644 index dc3c547c632..00000000000 --- a/spec/javascripts/todos_spec.js +++ /dev/null @@ -1,108 +0,0 @@ -import $ from 'jquery'; -import MockAdapter from 'axios-mock-adapter'; -import Todos from '~/pages/dashboard/todos/index/todos'; -import '~/lib/utils/common_utils'; -import '~/gl_dropdown'; -import axios from '~/lib/utils/axios_utils'; -import { addDelimiter } from '~/lib/utils/text_utility'; - -const TEST_COUNT_BIG = 2000; -const TEST_DONE_COUNT_BIG = 7300; - -describe('Todos', () => { - preloadFixtures('todos/todos.html'); - let todoItem; - let mock; - - beforeEach(() => { - loadFixtures('todos/todos.html'); - todoItem = document.querySelector('.todos-list .todo'); - mock = new MockAdapter(axios); - - return new Todos(); - }); - - afterEach(() => { - mock.restore(); - }); - - describe('goToTodoUrl', () => { - it('opens the todo url', done => { - const todoLink = todoItem.dataset.url; - - spyOnDependency(Todos, 'visitUrl').and.callFake(url => { - expect(url).toEqual(todoLink); - done(); - }); - - todoItem.click(); - }); - - describe('meta click', () => { - let visitUrlSpy; - let windowOpenSpy; - let metakeyEvent; - - beforeEach(() => { - metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true }); - visitUrlSpy = spyOnDependency(Todos, 'visitUrl').and.callFake(() => {}); - windowOpenSpy = spyOn(window, 'open').and.callFake(() => {}); - }); - - it('opens the todo url in another tab', () => { - const todoLink = todoItem.dataset.url; - - $('.todos-list .todo').trigger(metakeyEvent); - - expect(visitUrlSpy).not.toHaveBeenCalled(); - expect(windowOpenSpy).toHaveBeenCalledWith(todoLink, '_blank'); - }); - - it('run native funcionality when avatar is clicked', () => { - $('.todos-list a').on('click', e => e.preventDefault()); - $('.todos-list img').trigger(metakeyEvent); - - expect(visitUrlSpy).not.toHaveBeenCalled(); - expect(windowOpenSpy).not.toHaveBeenCalled(); - }); - }); - - describe('on done todo click', () => { - let onToggleSpy; - - beforeEach(done => { - const el = document.querySelector('.js-done-todo'); - const path = el.dataset.href; - - // Arrange - mock - .onDelete(path) - .replyOnce(200, { count: TEST_COUNT_BIG, done_count: TEST_DONE_COUNT_BIG }); - onToggleSpy = jasmine.createSpy('onToggle'); - $(document).on('todo:toggle', onToggleSpy); - - // Act - el.click(); - - // Wait for axios and HTML to udpate - setImmediate(done); - }); - - it('dispatches todo:toggle', () => { - expect(onToggleSpy).toHaveBeenCalledWith(jasmine.anything(), TEST_COUNT_BIG); - }); - - it('updates pending text', () => { - expect(document.querySelector('.todos-pending .badge').innerHTML).toEqual( - addDelimiter(TEST_COUNT_BIG), - ); - }); - - it('updates done text', () => { - expect(document.querySelector('.todos-done .badge').innerHTML).toEqual( - addDelimiter(TEST_DONE_COUNT_BIG), - ); - }); - }); - }); -}); |