diff options
Diffstat (limited to 'spec/javascripts')
18 files changed, 242 insertions, 180 deletions
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js index ebfd60198b2..694f94efcff 100644 --- a/spec/javascripts/commit/pipelines/pipelines_spec.js +++ b/spec/javascripts/commit/pipelines/pipelines_spec.js @@ -1,15 +1,15 @@ import Vue from 'vue'; -import PipelinesTable from '~/commit/pipelines/pipelines_table'; +import pipelinesTable from '~/commit/pipelines/pipelines_table.vue'; describe('Pipelines table in Commits and Merge requests', () => { const jsonFixtureName = 'pipelines/pipelines.json'; let pipeline; + let PipelinesTable; - preloadFixtures('static/pipelines_table.html.raw'); preloadFixtures(jsonFixtureName); beforeEach(() => { - loadFixtures('static/pipelines_table.html.raw'); + PipelinesTable = Vue.extend(pipelinesTable); const pipelines = getJSONFixture(jsonFixtureName).pipelines; pipeline = pipelines.find(p => p.id === 1); }); @@ -26,8 +26,11 @@ describe('Pipelines table in Commits and Merge requests', () => { Vue.http.interceptors.push(pipelinesEmptyResponse); this.component = new PipelinesTable({ - el: document.querySelector('#commit-pipeline-table-view'), - }); + propsData: { + endpoint: 'endpoint', + helpPagePath: 'foo', + }, + }).$mount(); }); afterEach(function () { @@ -58,8 +61,11 @@ describe('Pipelines table in Commits and Merge requests', () => { Vue.http.interceptors.push(pipelinesResponse); this.component = new PipelinesTable({ - el: document.querySelector('#commit-pipeline-table-view'), - }); + propsData: { + endpoint: 'endpoint', + helpPagePath: 'foo', + }, + }).$mount(); }); afterEach(() => { @@ -92,8 +98,11 @@ describe('Pipelines table in Commits and Merge requests', () => { Vue.http.interceptors.push(pipelinesErrorResponse); this.component = new PipelinesTable({ - el: document.querySelector('#commit-pipeline-table-view'), - }); + propsData: { + endpoint: 'endpoint', + helpPagePath: 'foo', + }, + }).$mount(); }); afterEach(function () { diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js index e54ea11b08c..3391cade541 100644 --- a/spec/javascripts/datetime_utility_spec.js +++ b/spec/javascripts/datetime_utility_spec.js @@ -16,6 +16,10 @@ import { timeIntervalInWords } from '~/lib/utils/datetime_utility'; const date = new Date(); date.setFullYear(date.getFullYear() + 1); + // Add a day to prevent a transient error. If date is even 1 second + // short of a full year, timeFor will return '11 months remaining' + date.setDate(date.getDate() + 1); + expect( gl.utils.timeFor(date), ).toBe('1 year remaining'); diff --git a/spec/javascripts/deploy_keys/components/key_spec.js b/spec/javascripts/deploy_keys/components/key_spec.js index a4b98f6140d..5b64cbb2dfc 100644 --- a/spec/javascripts/deploy_keys/components/key_spec.js +++ b/spec/javascripts/deploy_keys/components/key_spec.js @@ -14,6 +14,7 @@ describe('Deploy keys key', () => { propsData: { deployKey, store, + endpoint: 'https://test.host/dummy/endpoint', }, }).$mount(); }; diff --git a/spec/javascripts/deploy_keys/components/keys_panel_spec.js b/spec/javascripts/deploy_keys/components/keys_panel_spec.js index a69b39c35c4..08357d2b547 100644 --- a/spec/javascripts/deploy_keys/components/keys_panel_spec.js +++ b/spec/javascripts/deploy_keys/components/keys_panel_spec.js @@ -17,6 +17,7 @@ describe('Deploy keys panel', () => { keys: data.enabled_keys, showHelpBox: true, store, + endpoint: 'https://test.host/dummy/endpoint', }, }).$mount(); diff --git a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js index c92a147b937..9e2076dc383 100644 --- a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js @@ -4,6 +4,10 @@ import '~/filtered_search/filtered_search_tokenizer'; import '~/filtered_search/filtered_search_dropdown_manager'; describe('Filtered Search Dropdown Manager', () => { + beforeEach(() => { + spyOn(jQuery, 'ajax'); + }); + describe('addWordToInput', () => { function getInputValue() { return document.querySelector('.filtered-search').value; diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js index 6d00d71f145..8d239c9cc3f 100644 --- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js @@ -1,6 +1,7 @@ import * as recentSearchesStoreSrc from '~/filtered_search/stores/recent_searches_store'; import RecentSearchesService from '~/filtered_search/services/recent_searches_service'; import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error'; +import RecentSearchesRoot from '~/filtered_search/recent_searches_root'; import '~/lib/utils/url_utility'; import '~/lib/utils/common_utils'; import '~/filtered_search/filtered_search_token_keys'; @@ -71,6 +72,7 @@ describe('Filtered Search Manager', () => { beforeEach(() => { spyOn(RecentSearchesService, 'isAvailable').and.returnValue(isLocalStorageAvailable); spyOn(recentSearchesStoreSrc, 'default'); + spyOn(RecentSearchesRoot.prototype, 'render'); filteredSearchManager = new gl.FilteredSearchManager(); filteredSearchManager.setup(); @@ -104,6 +106,7 @@ describe('Filtered Search Manager', () => { it('should blur button', () => { const e = { + preventDefault: () => {}, currentTarget: { blur: () => {}, }, @@ -116,6 +119,7 @@ describe('Filtered Search Manager', () => { it('should not call search if there is no state', () => { const e = { + preventDefault: () => {}, currentTarget: { blur: () => {}, }, @@ -127,6 +131,7 @@ describe('Filtered Search Manager', () => { it('should call search when there is state', () => { const e = { + preventDefault: () => {}, currentTarget: { blur: () => {}, dataset: { diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb index a746a776548..0715f4d5f6b 100644 --- a/spec/javascripts/fixtures/merge_requests.rb +++ b/spec/javascripts/fixtures/merge_requests.rb @@ -55,13 +55,20 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont render_merge_request(example.description, merge_request) end + it 'merge_requests/changes_tab_with_comments.json' do |example| + create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) + create(:note_on_merge_request, author: admin, project: project, noteable: merge_request) + render_merge_request(example.description, merge_request, action: :diffs, format: :json) + end + private - def render_merge_request(fixture_file_name, merge_request) - get :show, + def render_merge_request(fixture_file_name, merge_request, action: :show, format: :html) + get action, namespace_id: project.namespace.to_param, project_id: project, - id: merge_request.to_param + id: merge_request.to_param, + format: format expect(response).to be_success store_frontend_fixture(response, fixture_file_name) diff --git a/spec/javascripts/fixtures/pipelines_table.html.haml b/spec/javascripts/fixtures/pipelines_table.html.haml deleted file mode 100644 index ad1682704bb..00000000000 --- a/spec/javascripts/fixtures/pipelines_table.html.haml +++ /dev/null @@ -1 +0,0 @@ -#commit-pipeline-table-view{ data: { endpoint: "endpoint", "help-page-path": "foo" } } diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 2ccc4f16192..276e01fc82f 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -51,7 +51,6 @@ describe('Issuable output', () => { }); afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, issueShowInterceptor); }); it('should render a title/description/edited and update title/description/edited on update', (done) => { diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js index 408349cc42d..f3fdbff01a6 100644 --- a/spec/javascripts/issue_show/components/description_spec.js +++ b/spec/javascripts/issue_show/components/description_spec.js @@ -95,5 +95,33 @@ describe('Description component', () => { done(); }); }); + + it('clears task status text when no tasks are present', (done) => { + vm.taskStatus = '0 of 0'; + + setTimeout(() => { + expect( + document.querySelector('.issuable-meta #task_status').textContent.trim(), + ).toBe(''); + + done(); + }); + }); + }); + + it('applies syntax highlighting and math when description changed', (done) => { + spyOn(vm, 'renderGFM').and.callThrough(); + spyOn($.prototype, 'renderGFM').and.callThrough(); + vm.descriptionHtml = 'changed'; + + Vue.nextTick(() => { + setTimeout(() => { + expect(vm.$refs['gfm-content']).toBeDefined(); + expect(vm.renderGFM).toHaveBeenCalled(); + expect($.prototype.renderGFM).toHaveBeenCalled(); + + done(); + }); + }); }); }); diff --git a/spec/javascripts/merge_request_notes_spec.js b/spec/javascripts/merge_request_notes_spec.js index e54acfa8e44..b6d0ce02c4f 100644 --- a/spec/javascripts/merge_request_notes_spec.js +++ b/spec/javascripts/merge_request_notes_spec.js @@ -7,54 +7,92 @@ import '~/render_gfm'; import '~/render_math'; import '~/notes'; +const upArrowKeyCode = 38; + describe('Merge request notes', () => { window.gon = window.gon || {}; window.gl = window.gl || {}; gl.utils = gl.utils || {}; - const fixture = 'merge_requests/diff_comment.html.raw'; - preloadFixtures(fixture); + const discussionTabFixture = 'merge_requests/diff_comment.html.raw'; + const changesTabJsonFixture = 'merge_requests/changes_tab_with_comments.json'; + preloadFixtures(discussionTabFixture, changesTabJsonFixture); - beforeEach(() => { - loadFixtures(fixture); - gl.utils.disableButtonIfEmptyField = _.noop; - window.project_uploads_path = 'http://test.host/uploads'; - $('body').data('page', 'projects:merge_requests:show'); - window.gon.current_user_id = $('.note:last').data('author-id'); + describe('Discussion tab with diff comments', () => { + beforeEach(() => { + loadFixtures(discussionTabFixture); + gl.utils.disableButtonIfEmptyField = _.noop; + window.project_uploads_path = 'http://test.host/uploads'; + $('body').data('page', 'projects:merge_requests:show'); + window.gon.current_user_id = $('.note:last').data('author-id'); - return new Notes('', []); - }); + return new Notes('', []); + }); + + describe('up arrow', () => { + it('edits last comment when triggered in main form', () => { + const upArrowEvent = $.Event('keydown'); + upArrowEvent.which = upArrowKeyCode; + + spyOnEvent('.note:last .js-note-edit', 'click'); + + $('.js-note-text').trigger(upArrowEvent); + + expect('click').toHaveBeenTriggeredOn('.note:last .js-note-edit'); + }); + + it('edits last comment in discussion when triggered in discussion form', (done) => { + const upArrowEvent = $.Event('keydown'); + upArrowEvent.which = upArrowKeyCode; + + spyOnEvent('.note-discussion .js-note-edit', 'click'); + + $('.js-discussion-reply-button').click(); - describe('up arrow', () => { - it('edits last comment when triggered in main form', () => { - const upArrowEvent = $.Event('keydown'); - upArrowEvent.which = 38; + setTimeout(() => { + expect( + $('.note-discussion .js-note-text'), + ).toExist(); - spyOnEvent('.note:last .js-note-edit', 'click'); + $('.note-discussion .js-note-text').trigger(upArrowEvent); - $('.js-note-text').trigger(upArrowEvent); + expect('click').toHaveBeenTriggeredOn('.note-discussion .js-note-edit'); - expect('click').toHaveBeenTriggeredOn('.note:last .js-note-edit'); + done(); + }); + }); }); + }); - it('edits last comment in discussion when triggered in discussion form', (done) => { - const upArrowEvent = $.Event('keydown'); - upArrowEvent.which = 38; + describe('Changes tab with diff comments', () => { + beforeEach(() => { + const diffsResponse = getJSONFixture(changesTabJsonFixture); + const noteFormHtml = `<form class="js-new-note-form"> + <textarea class="js-note-text"></textarea> + </form>`; + setFixtures(diffsResponse.html + noteFormHtml); + $('body').data('page', 'projects:merge_requests:show'); + window.gon.current_user_id = $('.note:last').data('author-id'); + + return new Notes('', []); + }); - spyOnEvent('.note-discussion .js-note-edit', 'click'); + describe('up arrow', () => { + it('edits last comment in discussion when triggered in discussion form', (done) => { + const upArrowEvent = $.Event('keydown'); + upArrowEvent.which = upArrowKeyCode; - $('.js-discussion-reply-button').click(); + spyOnEvent('.note:last .js-note-edit', 'click'); - setTimeout(() => { - expect( - $('.note-discussion .js-note-text'), - ).toExist(); + $('.js-discussion-reply-button').trigger('click'); - $('.note-discussion .js-note-text').trigger(upArrowEvent); + setTimeout(() => { + $('.js-note-text').trigger(upArrowEvent); - expect('click').toHaveBeenTriggeredOn('.note-discussion .js-note-edit'); + expect('click').toHaveBeenTriggeredOn('.note:last .js-note-edit'); - done(); + done(); + }); }); }); }); diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js index c6f218e4dac..5ece4ed080b 100644 --- a/spec/javascripts/notes_spec.js +++ b/spec/javascripts/notes_spec.js @@ -176,7 +176,7 @@ import '~/notes'; Notes.updateNoteTargetSelector($note); - expect($note.toggleClass).toHaveBeenCalledWith('target', null); + expect($note.toggleClass).toHaveBeenCalledWith('target', false); }); }); @@ -595,46 +595,46 @@ import '~/notes'; }); }); - describe('hasSlashCommands', () => { + describe('hasQuickActions', () => { beforeEach(() => { this.notes = new Notes('', []); }); - it('should return true when comment begins with a slash command', () => { + it('should return true when comment begins with a quick action', () => { const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this'; - const hasSlashCommands = this.notes.hasSlashCommands(sampleComment); + const hasQuickActions = this.notes.hasQuickActions(sampleComment); - expect(hasSlashCommands).toBeTruthy(); + expect(hasQuickActions).toBeTruthy(); }); - it('should return false when comment does NOT begin with a slash command', () => { + it('should return false when comment does NOT begin with a quick action', () => { const sampleComment = 'Hey, /unassign Merging this'; - const hasSlashCommands = this.notes.hasSlashCommands(sampleComment); + const hasQuickActions = this.notes.hasQuickActions(sampleComment); - expect(hasSlashCommands).toBeFalsy(); + expect(hasQuickActions).toBeFalsy(); }); - it('should return false when comment does NOT have any slash commands', () => { + it('should return false when comment does NOT have any quick actions', () => { const sampleComment = 'Looking good, Awesome!'; - const hasSlashCommands = this.notes.hasSlashCommands(sampleComment); + const hasQuickActions = this.notes.hasQuickActions(sampleComment); - expect(hasSlashCommands).toBeFalsy(); + expect(hasQuickActions).toBeFalsy(); }); }); - describe('stripSlashCommands', () => { - it('should strip slash commands from the comment which begins with a slash command', () => { + describe('stripQuickActions', () => { + it('should strip quick actions from the comment which begins with a quick action', () => { this.notes = new Notes(); const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this'; - const stripedComment = this.notes.stripSlashCommands(sampleComment); + const stripedComment = this.notes.stripQuickActions(sampleComment); expect(stripedComment).toBe(''); }); - it('should strip slash commands from the comment but leaves plain comment if it is present', () => { + it('should strip quick actions from the comment but leaves plain comment if it is present', () => { this.notes = new Notes(); const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign\nMerging this'; - const stripedComment = this.notes.stripSlashCommands(sampleComment); + const stripedComment = this.notes.stripQuickActions(sampleComment); expect(stripedComment).toBe('Merging this'); }); @@ -642,14 +642,14 @@ import '~/notes'; it('should NOT strip string that has slashes within', () => { this.notes = new Notes(); const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1'; - const stripedComment = this.notes.stripSlashCommands(sampleComment); + const stripedComment = this.notes.stripQuickActions(sampleComment); expect(stripedComment).toBe(sampleComment); }); }); - describe('getSlashCommandDescription', () => { - const availableSlashCommands = [ + describe('getQuickActionDescription', () => { + const availableQuickActions = [ { name: 'close', description: 'Close this issue', params: [] }, { name: 'title', description: 'Change title', params: [{}] }, { name: 'estimate', description: 'Set time estimate', params: [{}] } @@ -659,19 +659,19 @@ import '~/notes'; this.notes = new Notes(); }); - it('should return executing slash command description when note has single slash command', () => { + it('should return executing quick action description when note has single quick action', () => { const sampleComment = '/close'; - expect(this.notes.getSlashCommandDescription(sampleComment, availableSlashCommands)).toBe('Applying command to close this issue'); + expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe('Applying command to close this issue'); }); - it('should return generic multiple slash command description when note has multiple slash commands', () => { + it('should return generic multiple quick action description when note has multiple quick actions', () => { const sampleComment = '/close\n/title [Duplicate] Issue foobar'; - expect(this.notes.getSlashCommandDescription(sampleComment, availableSlashCommands)).toBe('Applying multiple commands'); + expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe('Applying multiple commands'); }); - it('should return generic slash command description when available slash commands list is not populated', () => { + it('should return generic quick action description when available quick actions list is not populated', () => { const sampleComment = '/close\n/title [Duplicate] Issue foobar'; - expect(this.notes.getSlashCommandDescription(sampleComment)).toBe('Applying command'); + expect(this.notes.getQuickActionDescription(sampleComment)).toBe('Applying command'); }); }); diff --git a/spec/javascripts/pipelines/async_button_spec.js b/spec/javascripts/pipelines/async_button_spec.js index 28c9c7ab282..48620898357 100644 --- a/spec/javascripts/pipelines/async_button_spec.js +++ b/spec/javascripts/pipelines/async_button_spec.js @@ -1,25 +1,20 @@ import Vue from 'vue'; import asyncButtonComp from '~/pipelines/components/async_button.vue'; +import eventHub from '~/pipelines/event_hub'; describe('Pipelines Async Button', () => { let component; - let spy; let AsyncButtonComponent; beforeEach(() => { AsyncButtonComponent = Vue.extend(asyncButtonComp); - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); - component = new AsyncButtonComponent({ propsData: { endpoint: '/foo', title: 'Foo', icon: 'fa fa-foo', cssClass: 'bar', - service: { - postAction: spy, - }, }, }).$mount(); }); @@ -33,7 +28,7 @@ describe('Pipelines Async Button', () => { }); it('should render the provided title', () => { - expect(component.$el.getAttribute('title')).toContain('Foo'); + expect(component.$el.getAttribute('data-original-title')).toContain('Foo'); expect(component.$el.getAttribute('aria-label')).toContain('Foo'); }); @@ -41,37 +36,12 @@ describe('Pipelines Async Button', () => { expect(component.$el.getAttribute('class')).toContain('bar'); }); - it('should call the service when it is clicked with the provided endpoint', () => { - component.$el.click(); - expect(spy).toHaveBeenCalledWith('/foo'); - }); - - it('should hide loading if request fails', () => { - spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); - - component = new AsyncButtonComponent({ - propsData: { - endpoint: '/foo', - title: 'Foo', - icon: 'fa fa-foo', - cssClass: 'bar', - dataAttributes: { - 'data-foo': 'foo', - }, - service: { - postAction: spy, - }, - }, - }).$mount(); - - component.$el.click(); - expect(component.$el.querySelector('.fa-spinner')).toBe(null); - }); - describe('With confirm dialog', () => { it('should call the service when confimation is positive', () => { spyOn(window, 'confirm').and.returnValue(true); - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); + eventHub.$on('postAction', (endpoint) => { + expect(endpoint).toEqual('/foo'); + }); component = new AsyncButtonComponent({ propsData: { @@ -79,15 +49,11 @@ describe('Pipelines Async Button', () => { title: 'Foo', icon: 'fa fa-foo', cssClass: 'bar', - service: { - postAction: spy, - }, confirmActionMessage: 'bar', }, }).$mount(); component.$el.click(); - expect(spy).toHaveBeenCalledWith('/foo'); }); }); }); diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js index 8a58b77f1e3..72fb0a8f9ef 100644 --- a/spec/javascripts/pipelines/pipelines_actions_spec.js +++ b/spec/javascripts/pipelines/pipelines_actions_spec.js @@ -3,7 +3,6 @@ import pipelinesActionsComp from '~/pipelines/components/pipelines_actions.vue'; describe('Pipelines Actions dropdown', () => { let component; - let spy; let actions; let ActionsComponent; @@ -22,14 +21,9 @@ describe('Pipelines Actions dropdown', () => { }, ]; - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); - component = new ActionsComponent({ propsData: { actions, - service: { - postAction: spy, - }, }, }).$mount(); }); @@ -40,31 +34,6 @@ describe('Pipelines Actions dropdown', () => { ).toEqual(actions.length); }); - it('should call the service when an action is clicked', () => { - component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); - component.$el.querySelector('.js-pipeline-action-link').click(); - - expect(spy).toHaveBeenCalledWith(actions[0].path); - }); - - it('should hide loading if request fails', () => { - spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); - - component = new ActionsComponent({ - propsData: { - actions, - service: { - postAction: spy, - }, - }, - }).$mount(); - - component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); - component.$el.querySelector('.js-pipeline-action-link').click(); - - expect(component.$el.querySelector('.fa-spinner')).toEqual(null); - }); - it('should render a disabled action when it\'s not playable', () => { expect( component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'), diff --git a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js b/spec/javascripts/pipelines/pipelines_table_row_spec.js index 9475ee28a03..7ce39dca112 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js +++ b/spec/javascripts/pipelines/pipelines_table_row_spec.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import tableRowComp from '~/vue_shared/components/pipelines_table_row.vue'; +import tableRowComp from '~/pipelines/components/pipelines_table_row.vue'; describe('Pipelines Table Row', () => { const jsonFixtureName = 'pipelines/pipelines.json'; diff --git a/spec/javascripts/vue_shared/components/pipelines_table_spec.js b/spec/javascripts/pipelines/pipelines_table_spec.js index 4c35d702004..3afe89c8db4 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_spec.js +++ b/spec/javascripts/pipelines/pipelines_table_spec.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import pipelinesTableComp from '~/vue_shared/components/pipelines_table.vue'; +import pipelinesTableComp from '~/pipelines/components/pipelines_table.vue'; import '~/lib/utils/datetime_utility'; describe('Pipelines Table', () => { @@ -22,7 +22,6 @@ describe('Pipelines Table', () => { component = new PipelinesTableComponent({ propsData: { pipelines: [], - service: {}, }, }).$mount(); }); @@ -48,7 +47,6 @@ describe('Pipelines Table', () => { const component = new PipelinesTableComponent({ propsData: { pipelines: [], - service: {}, }, }).$mount(); expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(0); @@ -58,10 +56,8 @@ describe('Pipelines Table', () => { describe('with data', () => { it('should render rows', () => { const component = new PipelinesTableComponent({ - el: document.querySelector('.test-dom-element'), propsData: { pipelines: [pipeline], - service: {}, }, }).$mount(); diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js index 3dba2e817ff..cc336180ff7 100644 --- a/spec/javascripts/project_title_spec.js +++ b/spec/javascripts/project_title_spec.js @@ -1,4 +1,3 @@ -/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, jasmine/no-expect-in-setup-teardown, max-len */ /* global Project */ import 'select2/select2'; @@ -7,47 +6,52 @@ import '~/api'; import '~/project_select'; import '~/project'; -(function() { - describe('Project Title', function() { - preloadFixtures('issues/open-issue.html.raw'); - loadJSONFixtures('projects.json'); +describe('Project Title', () => { + preloadFixtures('issues/open-issue.html.raw'); + loadJSONFixtures('projects.json'); - beforeEach(function() { - loadFixtures('issues/open-issue.html.raw'); + beforeEach(() => { + loadFixtures('issues/open-issue.html.raw'); - window.gon = {}; - window.gon.api_version = 'v3'; + window.gon = {}; + window.gon.api_version = 'v3'; - return this.project = new Project(); - }); + // eslint-disable-next-line no-new + new Project(); + }); - describe('project list', function() { - var fakeAjaxResponse = function fakeAjaxResponse(req) { - var d; - expect(req.url).toBe('/api/v3/projects.json?simple=true'); - expect(req.data).toEqual({ search: '', order_by: 'last_activity_at', per_page: 20, membership: true }); - d = $.Deferred(); - d.resolve(this.projects_data); - return d.promise(); - }; - - beforeEach((function(_this) { - return function() { - _this.projects_data = getJSONFixture('projects.json'); - return spyOn(jQuery, 'ajax').and.callFake(fakeAjaxResponse.bind(_this)); - }; - })(this)); - it('toggles dropdown', function() { - var menu = $('.js-dropdown-menu-projects'); - $('.js-projects-dropdown-toggle').click(); - expect(menu).toHaveClass('open'); - menu.find('.dropdown-menu-close-icon').click(); - expect(menu).not.toHaveClass('open'); + describe('project list', () => { + let reqUrl; + let reqData; + + beforeEach(() => { + const fakeResponseData = getJSONFixture('projects.json'); + spyOn(jQuery, 'ajax').and.callFake((req) => { + const def = $.Deferred(); + reqUrl = req.url; + reqData = req.data; + def.resolve(fakeResponseData); + return def.promise(); }); }); - afterEach(() => { - window.gon = {}; + it('toggles dropdown', () => { + const $menu = $('.js-dropdown-menu-projects'); + $('.js-projects-dropdown-toggle').click(); + expect($menu).toHaveClass('open'); + expect(reqUrl).toBe('/api/v3/projects.json?simple=true'); + expect(reqData).toEqual({ + search: '', + order_by: 'last_activity_at', + per_page: 20, + membership: true, + }); + $menu.find('.dropdown-menu-close-icon').click(); + expect($menu).not.toHaveClass('open'); }); }); -}).call(window); + + afterEach(() => { + window.gon = {}; + }); +}); diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js index 2c34402576b..f0d51bd0902 100644 --- a/spec/javascripts/test_bundle.js +++ b/spec/javascripts/test_bundle.js @@ -1,8 +1,14 @@ +/* eslint-disable jasmine/no-global-setup */ import $ from 'jquery'; import _ from 'underscore'; import 'jasmine-jquery'; import '~/commons'; +import Vue from 'vue'; +import VueResource from 'vue-resource'; + +Vue.use(VueResource); + // enable test fixtures jasmine.getFixtures().fixturesPath = '/base/spec/javascripts/fixtures'; jasmine.getJSONFixtures().fixturesPath = '/base/spec/javascripts/fixtures'; @@ -16,6 +22,32 @@ window.gl = window.gl || {}; window.gl.TEST_HOST = 'http://test.host'; window.gon = window.gon || {}; +// HACK: Chrome 59 disconnects if there are too many synchronous tests in a row +// because it appears to lock up the thread that communicates to Karma's socket +// This async beforeEach gets called on every spec and releases the JS thread long +// enough for the socket to continue to communicate. +// The downside is that it creates a minor performance penalty in the time it takes +// to run our unit tests. +beforeEach(done => done()); + +beforeAll(() => { + const origError = console.error; + spyOn(console, 'error').and.callFake((message) => { + if (/^\[Vue warn\]/.test(message)) { + fail(message); + } else { + origError(message); + } + }); +}); + +const builtinVueHttpInterceptors = Vue.http.interceptors.slice(); + +beforeEach(() => { + // restore interceptors so we have no remaining ones from previous tests + Vue.http.interceptors = builtinVueHttpInterceptors.slice(); +}); + // render all of our tests const testsContext = require.context('.', true, /_spec$/); testsContext.keys().forEach(function (path) { |