{{ warningMessage }}
+ + + + {{ + s__( + 'ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration.', + ) + }} + + ++ {{ + __( + 'Now you can access the merge request navigation tabs at the top, where they’re easier to find.', + ) + }} +
+
+
- {{ durationFormated }} + {{ durationFormatted }}
@@ -71,7 +71,7 @@ export default { data-placement="top" data-container="body" > - {{ timeFormated(finishedTime) }} + {{ timeFormatted(finishedTime) }}
+ {{ s__('PackageRegistry|Tag retention policies are designed to:') }} +
+---
- - - --
Expanded!
"`; + +exports[`Expand button when short text is provided renders button before text 1`] = `"Short
"`; diff --git a/spec/frontend/vue_shared/components/__snapshots__/memory_graph_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/memory_graph_spec.js.snap new file mode 100644 index 0000000000..a7f666ff56 --- /dev/null +++ b/spec/frontend/vue_shared/components/__snapshots__/memory_graph_spec.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MemoryGraph Render chart should draw container with chart 1`] = ` +${text.expanded}
`, + }, + }); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders the prepended collapse button', () => { + expect(expanderPrependEl().isVisible()).toBe(true); + expect(expanderAppendEl().isVisible()).toBe(false); + }); + + it('renders no text when short text is not provided', () => { + expect(wrapper.find(ExpandButton).text()).toBe(''); + }); + + it('does not render expanded text', () => { + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).not.toBe(text.short); + }); + + describe('when short text is provided', () => { + beforeEach(() => { + factory({ + slots: { + expanded: `${text.expanded}
`, + short: `${text.short}
`, + }, + }); + }); + + it('renders short text', () => { + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).toBe(text.short); + }); + + it('renders button before text', () => { + expect(expanderPrependEl().isVisible()).toBe(true); + expect(expanderAppendEl().isVisible()).toBe(false); + expect(wrapper.find(ExpandButton).html()).toMatchSnapshot(); + }); + }); + + describe('on click', () => { + beforeEach(done => { + expanderPrependEl().trigger('click'); + Vue.nextTick(done); + }); + + afterEach(() => { + expanderAppendEl().trigger('click'); + }); + + it('renders only the append collapse button', () => { + expect(expanderAppendEl().isVisible()).toBe(true); + expect(expanderPrependEl().isVisible()).toBe(false); + }); + + it('renders the expanded text', () => { + expect(wrapper.find(ExpandButton).text()).toContain(text.expanded); + }); + + describe('when short text is provided', () => { + beforeEach(done => { + factory({ + slots: { + expanded: `${text.expanded}
`, + short: `${text.short}
`, + }, + }); + + expanderPrependEl().trigger('click'); + Vue.nextTick(done); + }); + + it('only renders expanded text', () => { + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).toBe(text.expanded); + }); + + it('renders button after text', () => { + expect(expanderPrependEl().isVisible()).toBe(false); + expect(expanderAppendEl().isVisible()).toBe(true); + expect(wrapper.find(ExpandButton).html()).toMatchSnapshot(); + }); + }); + }); + + describe('append button', () => { + beforeEach(done => { + expanderPrependEl().trigger('click'); + Vue.nextTick(done); + }); + + it('clicking hides itself and shows prepend', () => { + expect(expanderAppendEl().isVisible()).toBe(true); + expanderAppendEl().trigger('click'); + expect(expanderPrependEl().isVisible()).toBe(true); + }); + + it('clicking hides expanded text', () => { + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).toBe(text.expanded); + expanderAppendEl().trigger('click'); + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).not.toBe(text.expanded); + }); + + describe('when short text is provided', () => { + beforeEach(done => { + factory({ + slots: { + expanded: `${text.expanded}
`, + short: `${text.short}
`, + }, + }); + + expanderPrependEl().trigger('click'); + Vue.nextTick(done); + }); + + it('clicking reveals short text', () => { + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).toBe(text.expanded); + expanderAppendEl().trigger('click'); + expect( + wrapper + .find(ExpandButton) + .text() + .trim(), + ).toBe(text.short); + }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js index f076c45e56..d9badffb50 100644 --- a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js +++ b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js @@ -1,7 +1,7 @@ import Vuex from 'vuex'; -import GlToggleVuex from '~/vue_shared/components/gl_toggle_vuex.vue'; import { GlToggle } from '@gitlab/ui'; import { mount, createLocalVue } from '@vue/test-utils'; +import GlToggleVuex from '~/vue_shared/components/gl_toggle_vuex.vue'; const localVue = createLocalVue(); localVue.use(Vuex); diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js index 9e6b528689..dcae2f1283 100644 --- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js +++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js @@ -18,6 +18,7 @@ describe('IssueAssigneesComponent', () => { ...props, }, sync: false, + attachToDocument: true, }); vm = wrapper.vm; // eslint-disable-line }; diff --git a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js index 2e93ec412b..4a66330ac3 100644 --- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js +++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js @@ -1,18 +1,20 @@ import Vue from 'vue'; -import { mount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue'; +import Icon from '~/vue_shared/components/icon.vue'; import { mockMilestone } from '../../../../javascripts/boards/mock_data'; const createComponent = (milestone = mockMilestone) => { const Component = Vue.extend(IssueMilestone); - return mount(Component, { + return shallowMount(Component, { propsData: { milestone, }, sync: false, + attachToDocument: true, }); }; @@ -156,7 +158,7 @@ describe('IssueMilestoneComponent', () => { }); it('renders milestone icon', () => { - expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('clock'); + expect(wrapper.find(Icon).props('name')).toBe('clock'); }); it('renders milestone title', () => { diff --git a/spec/frontend/vue_shared/components/issue/issue_warning_spec.js b/spec/frontend/vue_shared/components/issue/issue_warning_spec.js index 63880b8562..7bb054b4e6 100644 --- a/spec/frontend/vue_shared/components/issue/issue_warning_spec.js +++ b/spec/frontend/vue_shared/components/issue/issue_warning_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; -import issueWarning from '~/vue_shared/components/issue/issue_warning.vue'; import mountComponent from 'helpers/vue_mount_component_helper'; +import issueWarning from '~/vue_shared/components/issue/issue_warning.vue'; const IssueWarning = Vue.extend(issueWarning); diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js index b85e267362..3cc640cb00 100644 --- a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js +++ b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; -import { formatDate } from '~/lib/utils/datetime_utility'; import { mount, createLocalVue } from '@vue/test-utils'; +import { formatDate } from '~/lib/utils/datetime_utility'; import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue'; import { defaultAssignees, @@ -35,6 +35,7 @@ describe('RelatedIssuableItem', () => { localVue, slots, sync: false, + attachToDocument: true, propsData: props, }); }); @@ -89,11 +90,11 @@ describe('RelatedIssuableItem', () => { it('renders state title', () => { const stateTitle = tokenState.attributes('title'); - const formatedCreateDate = formatDate(props.createdAt); + const formattedCreateDate = formatDate(props.createdAt); expect(stateTitle).toContain('Opened'); - expect(stateTitle).toContain(`${formatedCreateDate}`); + expect(stateTitle).toContain(`${formattedCreateDate}`); }); it('renders aria label', () => { diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js new file mode 100644 index 0000000000..4cd0f62da0 --- /dev/null +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -0,0 +1,179 @@ +import { mount, createLocalVue } from '@vue/test-utils'; +import { TEST_HOST } from 'spec/test_constants'; +import AxiosMockAdapter from 'axios-mock-adapter'; +import $ from 'jquery'; +import axios from '~/lib/utils/axios_utils'; +import fieldComponent from '~/vue_shared/components/markdown/field.vue'; + +const markdownPreviewPath = `${TEST_HOST}/preview`; +const markdownDocsPath = `${TEST_HOST}/docs`; + +function assertMarkdownTabs(isWrite, writeLink, previewLink, wrapper) { + expect(writeLink.element.parentNode.classList.contains('active')).toEqual(isWrite); + expect(previewLink.element.parentNode.classList.contains('active')).toEqual(!isWrite); + expect(wrapper.find('.md-preview-holder').element.style.display).toEqual(isWrite ? 'none' : ''); +} + +function createComponent() { + const wrapper = mount(fieldComponent, { + propsData: { + markdownDocsPath, + markdownPreviewPath, + }, + slots: { + textarea: '', + }, + template: ` +markdown preview
'; + let previewLink; + let writeLink; + + it('renders textarea inside backdrop', () => { + wrapper = createComponent(); + expect(wrapper.find('.zen-backdrop textarea').element).not.toBeNull(); + }); + + describe('markdown preview', () => { + beforeEach(() => { + axiosMock.onPost(markdownPreviewPath).reply(200, { body: previewHTML }); + }); + + it('sets preview link as active', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + return localVue.nextTick().then(() => { + expect(previewLink.element.parentNode.classList.contains('active')).toBeTruthy(); + }); + }); + + it('shows preview loading text', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + localVue.nextTick(() => { + expect(wrapper.find('.md-preview-holder').element.textContent.trim()).toContain( + 'Loading…', + ); + }); + }); + + it('renders markdown preview', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + setTimeout(() => { + expect(wrapper.find('.md-preview-holder').element.innerHTML).toContain(previewHTML); + }); + }); + + it('renders GFM with jQuery', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + jest.spyOn($.fn, 'renderGFM'); + + previewLink.trigger('click'); + + setTimeout(() => { + expect($.fn.renderGFM).toHaveBeenCalled(); + }, 0); + }); + + it('clicking already active write or preview link does nothing', () => { + wrapper = createComponent(); + writeLink = getWriteLink(wrapper); + previewLink = getPreviewLink(wrapper); + + writeLink.trigger('click'); + return localVue + .nextTick() + .then(() => assertMarkdownTabs(true, writeLink, previewLink, wrapper)) + .then(() => writeLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(true, writeLink, previewLink, wrapper)) + .then(() => previewLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(false, writeLink, previewLink, wrapper)) + .then(() => previewLink.trigger('click')) + .then(() => localVue.nextTick()) + .then(() => assertMarkdownTabs(false, writeLink, previewLink, wrapper)); + }); + }); + + describe('markdown buttons', () => { + it('converts single words', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 7); + const markdownButton = getMarkdownButton(wrapper); + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('**testing**'); + }); + }); + + it('converts a line', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 0); + const markdownButton = getAllMarkdownButtons(wrapper).wrappers[5]; + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('* testing'); + }); + }); + + it('converts multiple lines', () => { + wrapper = createComponent(); + const textarea = wrapper.find('textarea').element; + textarea.setSelectionRange(0, 50); + const markdownButton = getAllMarkdownButtons(wrapper).wrappers[5]; + markdownButton.trigger('click'); + + localVue.nextTick(() => { + expect(textarea.value).toContain('* testing\n* 123'); + }); + }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js index 48f2ee8661..1014fbf030 100644 --- a/spec/frontend/vue_shared/components/markdown/header_spec.js +++ b/spec/frontend/vue_shared/components/markdown/header_spec.js @@ -1,20 +1,35 @@ -import Vue from 'vue'; +import { shallowMount } from '@vue/test-utils'; import $ from 'jquery'; -import headerComponent from '~/vue_shared/components/markdown/header.vue'; +import HeaderComponent from '~/vue_shared/components/markdown/header.vue'; +import ToolbarButton from '~/vue_shared/components/markdown/toolbar_button.vue'; describe('Markdown field header component', () => { - let vm; + let wrapper; - beforeEach(done => { - const Component = Vue.extend(headerComponent); - - vm = new Component({ + const createWrapper = props => { + wrapper = shallowMount(HeaderComponent, { propsData: { previewMarkdown: false, + ...props, }, - }).$mount(); + sync: false, + attachToDocument: true, + }); + }; - Vue.nextTick(done); + const findToolbarButtons = () => wrapper.findAll(ToolbarButton); + const findToolbarButtonByProp = (prop, value) => + findToolbarButtons() + .filter(button => button.props(prop) === value) + .at(0); + + beforeEach(() => { + createWrapper(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; }); it('renders markdown header buttons', () => { @@ -31,77 +46,72 @@ describe('Markdown field header component', () => { 'Add a table', 'Go full screen', ]; - const elements = vm.$el.querySelectorAll('.toolbar-btn'); + const elements = findToolbarButtons(); - elements.forEach((buttonEl, index) => { - expect(buttonEl.getAttribute('data-original-title')).toBe(buttons[index]); + elements.wrappers.forEach((buttonEl, index) => { + expect(buttonEl.props('buttonTitle')).toBe(buttons[index]); }); }); it('renders `write` link as active when previewMarkdown is false', () => { - expect(vm.$el.querySelector('li:nth-child(1)').classList.contains('active')).toBeTruthy(); + expect(wrapper.find('li:nth-child(1)').classes()).toContain('active'); }); - it('renders `preview` link as active when previewMarkdown is true', done => { - vm.previewMarkdown = true; + it('renders `preview` link as active when previewMarkdown is true', () => { + createWrapper({ previewMarkdown: true }); - Vue.nextTick(() => { - expect(vm.$el.querySelector('li:nth-child(2)').classList.contains('active')).toBeTruthy(); - - done(); - }); + expect(wrapper.find('li:nth-child(2)').classes()).toContain('active'); }); it('emits toggle markdown event when clicking preview', () => { - jest.spyOn(vm, '$emit').mockImplementation(); + wrapper.find('.js-preview-link').trigger('click'); - vm.$el.querySelector('.js-preview-link').click(); + expect(wrapper.emitted('preview-markdown').length).toEqual(1); - expect(vm.$emit).toHaveBeenCalledWith('preview-markdown'); + wrapper.find('.js-write-link').trigger('click'); - vm.$el.querySelector('.js-write-link').click(); - - expect(vm.$emit).toHaveBeenCalledWith('write-markdown'); + expect(wrapper.emitted('write-markdown').length).toEqual(1); }); it('does not emit toggle markdown event when triggered from another form', () => { - jest.spyOn(vm, '$emit').mockImplementation(); - $(document).triggerHandler('markdown-preview:show', [ $( '', ), ]); - expect(vm.$emit).not.toHaveBeenCalled(); + expect(wrapper.emitted('preview-markdown')).toBeFalsy(); + expect(wrapper.emitted('write-markdown')).toBeFalsy(); }); it('blurs preview link after click', () => { - const link = vm.$el.querySelector('li:nth-child(2) button'); + const link = wrapper.find('li:nth-child(2) button'); jest.spyOn(HTMLElement.prototype, 'blur').mockImplementation(); - link.click(); + link.trigger('click'); - expect(link.blur).toHaveBeenCalled(); + expect(link.element.blur).toHaveBeenCalled(); }); it('renders markdown table template', () => { - expect(vm.mdTable).toEqual( + const tableButton = findToolbarButtonByProp('icon', 'table'); + + expect(tableButton.props('tag')).toEqual( '| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |', ); }); it('renders suggestion template', () => { - vm.lineContent = 'Some content'; - - expect(vm.mdSuggestion).toEqual('```suggestion:-0+0\n{text}\n```'); + expect(findToolbarButtonByProp('buttonTitle', 'Insert suggestion').props('tag')).toEqual( + '```suggestion:-0+0\n{text}\n```', + ); }); it('does not render suggestion button if `canSuggest` is set to false', () => { - vm.canSuggest = false; - - Vue.nextTick(() => { - expect(vm.$el.querySelector('.js-suggestion-btn')).toBe(null); + createWrapper({ + canSuggest: false, }); + + expect(wrapper.find('.js-suggestion-btn').exists()).toBe(false); }); }); diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js index 6716e5cd79..71f9b5e324 100644 --- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js +++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js @@ -21,6 +21,7 @@ describe('Suggestion Diff component', () => { }, localVue, sync: false, + attachToDocument: true, }); }; @@ -64,12 +65,10 @@ describe('Suggestion Diff component', () => { }); describe('when apply suggestion is clicked', () => { - beforeEach(done => { + beforeEach(() => { createComponent(); findApplyButton().vm.$emit('click'); - - wrapper.vm.$nextTick(done); }); it('emits apply', () => { @@ -88,19 +87,15 @@ describe('Suggestion Diff component', () => { expect(wrapper.text()).toContain('Applying suggestion'); }); - it('when callback of apply is called, hides loading', done => { + it('when callback of apply is called, hides loading', () => { const [callback] = wrapper.emitted().apply[0]; callback(); - wrapper.vm - .$nextTick() - .then(() => { - expect(findApplyButton().exists()).toBe(true); - expect(findLoading().exists()).toBe(false); - }) - .then(done) - .catch(done.fail); + return wrapper.vm.$nextTick().then(() => { + expect(findApplyButton().exists()).toBe(true); + expect(findLoading().exists()).toBe(false); + }); }); }); }); diff --git a/spec/frontend/vue_shared/components/memory_graph_spec.js b/spec/frontend/vue_shared/components/memory_graph_spec.js new file mode 100644 index 0000000000..9a5ee544d8 --- /dev/null +++ b/spec/frontend/vue_shared/components/memory_graph_spec.js @@ -0,0 +1,53 @@ +import Vue from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import { GlSparklineChart } from '@gitlab/ui/dist/charts'; +import MemoryGraph from '~/vue_shared/components/memory_graph.vue'; + +describe('MemoryGraph', () => { + const Component = Vue.extend(MemoryGraph); + let wrapper; + const metrics = [ + [1573586253.853, '2.87'], + [1573586313.853, '2.77734375'], + [1573586373.853, '2.77734375'], + [1573586433.853, '3.0066964285714284'], + ]; + + afterEach(() => { + wrapper.destroy(); + }); + + beforeEach(() => { + wrapper = shallowMount(Component, { + propsData: { + metrics, + width: 100, + height: 25, + }, + }); + }); + + describe('chartData', () => { + it('should calculate chartData', () => { + expect(wrapper.vm.chartData.length).toEqual(metrics.length); + }); + + it('should format date & MB values', () => { + const formattedData = [ + ['Nov 12 2019 19:17:33', '2.87'], + ['Nov 12 2019 19:18:33', '2.78'], + ['Nov 12 2019 19:19:33', '2.78'], + ['Nov 12 2019 19:20:33', '3.01'], + ]; + expect(wrapper.vm.chartData).toEqual(formattedData); + }); + }); + + describe('Render chart', () => { + it('should draw container with chart', () => { + expect(wrapper.element).toMatchSnapshot(); + expect(wrapper.find('.memory-graph-container').exists()).toBe(true); + expect(wrapper.find(GlSparklineChart).exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js index d8c55bee8e..3c71cb16bd 100644 --- a/spec/frontend/vue_shared/components/modal_copy_button_spec.js +++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js @@ -16,6 +16,8 @@ describe('modal copy button', () => { text: 'copy me', title: 'Copy this value', }, + attachToDocument: true, + sync: false, }); }); diff --git a/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js b/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js index 976e38c15e..81c5cd6a05 100644 --- a/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js +++ b/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; -import placeholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue'; import mountComponent from 'helpers/vue_mount_component_helper'; +import placeholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue'; describe('placeholder system note component', () => { let PlaceholderSystemNote; diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js index c2e8359f78..603c37c6c4 100644 --- a/spec/frontend/vue_shared/components/notes/system_note_spec.js +++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js @@ -1,10 +1,12 @@ -import Vue from 'vue'; -import issueSystemNote from '~/vue_shared/components/notes/system_note.vue'; +import { createLocalVue, mount } from '@vue/test-utils'; +import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue'; import createStore from '~/notes/stores'; import initMRPopovers from '~/mr_popover/index'; jest.mock('~/mr_popover/index', () => jest.fn()); +const localVue = createLocalVue(); + describe('system note component', () => { let vm; let props; @@ -30,34 +32,36 @@ describe('system note component', () => { const store = createStore(); store.dispatch('setTargetNoteHash', `note_${props.note.id}`); - const Component = Vue.extend(issueSystemNote); - vm = new Component({ + vm = mount(IssueSystemNote, { store, + localVue, propsData: props, - }).$mount(); + attachToDocument: true, + sync: false, + }); }); afterEach(() => { - vm.$destroy(); + vm.destroy(); }); it('should render a list item with correct id', () => { - expect(vm.$el.getAttribute('id')).toEqual(`note_${props.note.id}`); + expect(vm.attributes('id')).toEqual(`note_${props.note.id}`); }); it('should render target class is note is target note', () => { - expect(vm.$el.classList).toContain('target'); + expect(vm.classes()).toContain('target'); }); it('should render svg icon', () => { - expect(vm.$el.querySelector('.timeline-icon svg')).toBeDefined(); + expect(vm.find('.timeline-icon svg').exists()).toBe(true); }); // Redcarpet Markdown renderer wraps text in `` tags
// we need to strip them because they break layout of commit lists in system notes:
// https://gitlab.com/gitlab-org/gitlab-foss/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png
it('removes wrapping paragraph from note HTML', () => {
- expect(vm.$el.querySelector('.system-note-message').innerHTML).toContain('closed');
+ expect(vm.find('.system-note-message').html()).toContain('closed');
});
it('should initMRPopovers onMount', () => {
diff --git a/spec/frontend/vue_shared/components/paginated_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
index 31ac362d35..4e1b29a4d3 100644
--- a/spec/frontend/vue_shared/components/paginated_list_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -1,6 +1,6 @@
+import { mount } from '@vue/test-utils';
import PaginatedList from '~/vue_shared/components/paginated_list.vue';
import { PREV, NEXT } from '~/vue_shared/components/pagination/constants';
-import { mount } from '@vue/test-utils';
describe('Pagination links component', () => {
let wrapper;
@@ -26,6 +26,8 @@ describe('Pagination links component', () => {
list: [{ id: 'foo' }, { id: 'bar' }],
props,
},
+ attachToDocument: true,
+ sync: false,
});
[glPaginatedList] = wrapper.vm.$children;
diff --git a/spec/frontend/vue_shared/components/resizable_chart_container_spec.js b/spec/frontend/vue_shared/components/resizable_chart_container_spec.js
index 8f533e8ab2..552cfade7b 100644
--- a/spec/frontend/vue_shared/components/resizable_chart_container_spec.js
+++ b/spec/frontend/vue_shared/components/resizable_chart_container_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { mount } from '@vue/test-utils';
-import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
import $ from 'jquery';
+import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
jest.mock('~/lib/utils/common_utils', () => ({
debounceByAnimationFrame(callback) {
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
index 691ebe43d6..31316a93ec 100644
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import collapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+import collapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
describe('collapsedCalendarIcon', () => {
let vm;
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
index 062ebfa01c..65255968bc 100644
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import collapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+import collapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
describe('collapsedGroupedDatePicker', () => {
let vm;
diff --git a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
index 5e2bca6efc..198af09c9f 100644
--- a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import sidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+import sidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
describe('sidebarDatePicker', () => {
let vm;
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
index 6aee616c32..da22034a8d 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
@@ -1,22 +1,20 @@
import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
import LabelsSelect from '~/labels_select';
-import baseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
+import BaseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
-import { mount } from '@vue/test-utils';
import {
mockConfig,
mockLabels,
} from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
-const createComponent = (config = mockConfig) => {
- const Component = Vue.extend(baseComponent);
-
- return mount(Component, {
+const createComponent = (config = mockConfig) =>
+ shallowMount(BaseComponent, {
propsData: config,
sync: false,
+ attachToDocument: true,
});
-};
describe('BaseComponent', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
index bb33dc6ea0..e2e11c94c0 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import dropdownButtonComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_button.vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import {
mockConfig,
mockLabels,
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
index 1c25d42682..d029952313 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { mockSuggestedColors } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
const createComponent = headerTitle => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
index 989901a001..784bbaf8e6 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import dropdownFooterComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_footer.vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { mockConfig } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
const createComponent = (
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
index c36a82e1a3..2e721d75b4 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
-
import mountComponent from 'helpers/vue_mount_component_helper';
+import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
const createComponent = () => {
const Component = Vue.extend(dropdownHeaderComponent);
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
index 2fffb2e495..035af946d7 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
-
import mountComponent from 'helpers/vue_mount_component_helper';
+import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
const createComponent = () => {
const Component = Vue.extend(dropdownSearchInputComponent);
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
index 1616e657c8..2fffb31acf 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
-
import mountComponent from 'helpers/vue_mount_component_helper';
+import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
const createComponent = (canEdit = true) => {
const Component = Vue.extend(dropdownTitleComponent);
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
index 517f2c01c4..887c04268d 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { mockLabels } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
const createComponent = (labels = mockLabels) => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
index ec143fec5d..52c0298603 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
@@ -1,24 +1,31 @@
-import Vue from 'vue';
-import $ from 'jquery';
+import { mount } from '@vue/test-utils';
+import { hexToRgb } from '~/lib/utils/color_utils';
+import DropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
+import DropdownValueScopedLabel from '~/vue_shared/components/sidebar/labels_select/dropdown_value_scoped_label.vue';
-import dropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
import {
mockConfig,
mockLabels,
} from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+const labelStyles = {
+ textColor: '#FFFFFF',
+ color: '#BADA55',
+};
const createComponent = (
labels = mockLabels,
labelFilterBasePath = mockConfig.labelFilterBasePath,
) => {
- const Component = Vue.extend(dropdownValueComponent);
+ labels.forEach(label => Object.assign(label, labelStyles));
- return mountComponent(Component, {
- labels,
- labelFilterBasePath,
- enableScopedLabels: true,
+ return mount(DropdownValueComponent, {
+ propsData: {
+ labels,
+ labelFilterBasePath,
+ enableScopedLabels: true,
+ },
+ attachToDocument: true,
+ sync: false,
});
};
@@ -30,7 +37,7 @@ describe('DropdownValueComponent', () => {
});
afterEach(() => {
- vm.$destroy();
+ vm.destroy();
});
describe('computed', () => {
@@ -38,12 +45,12 @@ describe('DropdownValueComponent', () => {
it('returns true if `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
- expect(vmEmptyLabels.isEmpty).toBe(true);
- vmEmptyLabels.$destroy();
+ expect(vmEmptyLabels.classes()).not.toContain('has-labels');
+ vmEmptyLabels.destroy();
});
it('returns false if `labels` prop is empty', () => {
- expect(vm.isEmpty).toBe(false);
+ expect(vm.classes()).toContain('has-labels');
});
});
});
@@ -51,88 +58,71 @@ describe('DropdownValueComponent', () => {
describe('methods', () => {
describe('labelFilterUrl', () => {
it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
- expect(
- vm.labelFilterUrl({
- title: 'Foo bar',
- }),
- ).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
+ expect(vm.find(DropdownValueScopedLabel).props('labelFilterUrl')).toBe(
+ '/gitlab-org/my-project/issues?label_name[]=Foo%3A%3ABar',
+ );
});
});
describe('labelStyle', () => {
it('returns object with `color` & `backgroundColor` properties from label.textColor & label.color', () => {
- const label = {
- textColor: '#FFFFFF',
- color: '#BADA55',
- };
- const styleObj = vm.labelStyle(label);
-
- expect(styleObj.color).toBe(label.textColor);
- expect(styleObj.backgroundColor).toBe(label.color);
- });
- });
-
- describe('scopedLabelsDescription', () => {
- it('returns html for tooltip', () => {
- const html = vm.scopedLabelsDescription(mockLabels[1]);
- const $el = $.parseHTML(html);
-
- expect($el[0]).toHaveClass('scoped-label-tooltip-title');
- expect($el[2].textContent).toEqual(mockLabels[1].description);
+ expect(vm.find(DropdownValueScopedLabel).props('labelStyle')).toEqual({
+ color: labelStyles.textColor,
+ backgroundColor: labelStyles.color,
+ });
});
});
describe('showScopedLabels', () => {
it('returns true if the label is scoped label', () => {
- expect(vm.showScopedLabels(mockLabels[1])).toBe(true);
- });
-
- it('returns false when label is a regular label', () => {
- expect(vm.showScopedLabels(mockLabels[0])).toBe(false);
+ expect(vm.findAll(DropdownValueScopedLabel).length).toEqual(1);
});
});
});
describe('template', () => {
it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
- expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(
- true,
- );
+ expect(vm.classes()).toContain('hide-collapsed', 'value', 'issuable-show-labels');
});
it('render slot content inside component when `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
- expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(
- mockConfig.emptyValueText,
- );
- vmEmptyLabels.$destroy();
+ expect(
+ vmEmptyLabels
+ .find('.text-secondary')
+ .text()
+ .trim(),
+ ).toBe(mockConfig.emptyValueText);
+ vmEmptyLabels.destroy();
});
it('renders label element with filter URL', () => {
- expect(vm.$el.querySelector('a').getAttribute('href')).toBe(
+ expect(vm.find('a').attributes('href')).toBe(
'/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
);
});
it('renders label element and styles based on label details', () => {
- const labelEl = vm.$el.querySelector('a span.badge.color-label');
+ const labelEl = vm.find('a span.badge.color-label');
- expect(labelEl).not.toBeNull();
- expect(labelEl.getAttribute('style')).toBe('background-color: rgb(186, 218, 85);');
- expect(labelEl.innerText.trim()).toBe(mockLabels[0].title);
+ expect(labelEl.exists()).toBe(true);
+ expect(labelEl.attributes('style')).toContain(
+ `background-color: rgb(${hexToRgb(labelStyles.color).join(', ')});`,
+ );
+ expect(labelEl.text().trim()).toBe(mockLabels[0].title);
});
describe('label is of scoped-label type', () => {
it('renders a scoped-label-wrapper span to incorporate 2 anchors', () => {
- expect(vm.$el.querySelector('span.scoped-label-wrapper')).not.toBeNull();
+ expect(vm.find('span.scoped-label-wrapper').exists()).toBe(true);
});
it('renders anchor tag containing question icon', () => {
- const anchor = vm.$el.querySelector('.scoped-label-wrapper a.scoped-label');
+ const anchor = vm.find('.scoped-label-wrapper a.scoped-label');
- expect(anchor).not.toBeNull();
- expect(anchor.querySelector('i.fa-question-circle')).not.toBeNull();
+ expect(anchor.exists()).toBe(true);
+ expect(anchor.find('i.fa-question-circle').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
index 5cf25ca6f8..4342f5e210 100644
--- a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import toggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+import toggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
describe('toggleSidebar', () => {
let vm;
diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js
index 0a9ff36b2f..8105d1fcef 100644
--- a/spec/frontend/vue_shared/components/table_pagination_spec.js
+++ b/spec/frontend/vue_shared/components/table_pagination_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { GlPagination } from '@gitlab/ui';
describe('Pagination component', () => {
let wrapper;
@@ -12,15 +13,6 @@ describe('Pagination component', () => {
});
};
- const findFirstButtonLink = () => wrapper.find('.js-first-button .page-link');
- const findPreviousButton = () => wrapper.find('.js-previous-button');
- const findPreviousButtonLink = () => wrapper.find('.js-previous-button .page-link');
- const findNextButton = () => wrapper.find('.js-next-button');
- const findNextButtonLink = () => wrapper.find('.js-next-button .page-link');
- const findLastButtonLink = () => wrapper.find('.js-last-button .page-link');
- const findPages = () => wrapper.findAll('.page');
- const findSeparator = () => wrapper.find('.separator');
-
beforeEach(() => {
spy = jest.fn();
});
@@ -46,290 +38,54 @@ describe('Pagination component', () => {
expect(wrapper.isEmpty()).toBe(true);
});
- describe('prev button', () => {
- it('should be disabled and non clickable', () => {
- mountComponent({
- pageInfo: {
- nextPage: 2,
- page: 1,
- perPage: 20,
- previousPage: NaN,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
-
- expect(findPreviousButton().classes()).toContain('disabled');
- findPreviousButtonLink().trigger('click');
- expect(spy).not.toHaveBeenCalled();
+ it('renders if there is a next page', () => {
+ mountComponent({
+ pageInfo: {
+ nextPage: 2,
+ page: 1,
+ perPage: 20,
+ previousPage: NaN,
+ total: 15,
+ totalPages: 1,
+ },
+ change: spy,
});
- it('should be disabled and non clickable when total and totalPages are NaN', () => {
- mountComponent({
- pageInfo: {
- nextPage: 2,
- page: 1,
- perPage: 20,
- previousPage: NaN,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- expect(findPreviousButton().classes()).toContain('disabled');
- findPreviousButtonLink().trigger('click');
- expect(spy).not.toHaveBeenCalled();
- });
-
- it('should be enabled and clickable', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- findPreviousButtonLink().trigger('click');
- expect(spy).toHaveBeenCalledWith(1);
- });
-
- it('should be enabled and clickable when total and totalPages are NaN', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- findPreviousButtonLink().trigger('click');
- expect(spy).toHaveBeenCalledWith(1);
- });
+ expect(wrapper.isEmpty()).toBe(false);
});
- describe('first button', () => {
- it('should call the change callback with the first page', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- const button = findFirstButtonLink();
- expect(button.text().trim()).toEqual('« First');
- button.trigger('click');
- expect(spy).toHaveBeenCalledWith(1);
+ it('renders if there is a prev page', () => {
+ mountComponent({
+ pageInfo: {
+ nextPage: NaN,
+ page: 2,
+ perPage: 20,
+ previousPage: 1,
+ total: 15,
+ totalPages: 1,
+ },
+ change: spy,
});
- it('should call the change callback with the first page when total and totalPages are NaN', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- const button = findFirstButtonLink();
- expect(button.text().trim()).toEqual('« First');
- button.trigger('click');
- expect(spy).toHaveBeenCalledWith(1);
- });
+ expect(wrapper.isEmpty()).toBe(false);
});
+ });
- describe('last button', () => {
- it('should call the change callback with the last page', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- const button = findLastButtonLink();
- expect(button.text().trim()).toEqual('Last »');
- button.trigger('click');
- expect(spy).toHaveBeenCalledWith(5);
- });
-
- it('should not render', () => {
- mountComponent({
- pageInfo: {
- nextPage: 3,
- page: 2,
- perPage: 20,
- previousPage: 1,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- expect(findLastButtonLink().exists()).toBe(false);
- });
- });
-
- describe('next button', () => {
- it('should be disabled and non clickable', () => {
- mountComponent({
- pageInfo: {
- nextPage: NaN,
- page: 5,
- perPage: 20,
- previousPage: 4,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- expect(
- findNextButton()
- .text()
- .trim(),
- ).toEqual('Next ›');
- findNextButtonLink().trigger('click');
- expect(spy).not.toHaveBeenCalled();
- });
-
- it('should be disabled and non clickable when total and totalPages are NaN', () => {
- mountComponent({
- pageInfo: {
- nextPage: NaN,
- page: 5,
- perPage: 20,
- previousPage: 4,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- expect(
- findNextButton()
- .text()
- .trim(),
- ).toEqual('Next ›');
- findNextButtonLink().trigger('click');
- expect(spy).not.toHaveBeenCalled();
- });
-
- it('should be enabled and clickable', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- findNextButtonLink().trigger('click');
- expect(spy).toHaveBeenCalledWith(4);
- });
-
- it('should be enabled and clickable when total and totalPages are NaN', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- findNextButtonLink().trigger('click');
- expect(spy).toHaveBeenCalledWith(4);
- });
- });
-
- describe('numbered buttons', () => {
- it('should render 5 pages', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: 84,
- totalPages: 5,
- },
- change: spy,
- });
- expect(findPages().length).toEqual(5);
- });
-
- it('should not render any page', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- expect(findPages().length).toEqual(0);
- });
- });
-
- describe('spread operator', () => {
- it('should render', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: 84,
- totalPages: 10,
- },
- change: spy,
- });
- expect(
- findSeparator()
- .text()
- .trim(),
- ).toEqual('...');
- });
-
- it('should not render', () => {
- mountComponent({
- pageInfo: {
- nextPage: 4,
- page: 3,
- perPage: 20,
- previousPage: 2,
- total: NaN,
- totalPages: NaN,
- },
- change: spy,
- });
- expect(findSeparator().exists()).toBe(false);
+ describe('events', () => {
+ it('calls change method when page changes', () => {
+ mountComponent({
+ pageInfo: {
+ nextPage: NaN,
+ page: 2,
+ perPage: 20,
+ previousPage: 1,
+ total: 15,
+ totalPages: 1,
+ },
+ change: spy,
});
+ wrapper.find(GlPagination).vm.$emit('input', 3);
+ expect(spy).toHaveBeenCalledWith(3);
});
});
});
diff --git a/spec/frontend/vue_shared/components/time_ago_tooltip_spec.js b/spec/frontend/vue_shared/components/time_ago_tooltip_spec.js
index 536bb57b94..f1f231c1a2 100644
--- a/spec/frontend/vue_shared/components/time_ago_tooltip_spec.js
+++ b/spec/frontend/vue_shared/components/time_ago_tooltip_spec.js
@@ -1,44 +1,40 @@
-import Vue from 'vue';
-import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
describe('Time ago with tooltip component', () => {
- let TimeagoTooltip;
let vm;
- beforeEach(() => {
- TimeagoTooltip = Vue.extend(timeagoTooltip);
- });
+ const buildVm = (propsData = {}) => {
+ vm = shallowMount(TimeAgoTooltip, {
+ attachToDocument: true,
+ sync: false,
+ propsData,
+ localVue: createLocalVue(),
+ });
+ };
+ const timestamp = '2017-05-08T14:57:39.781Z';
afterEach(() => {
- vm.$destroy();
+ vm.destroy();
});
it('should render timeago with a bootstrap tooltip', () => {
- vm = new TimeagoTooltip({
- propsData: {
- time: '2017-05-08T14:57:39.781Z',
- },
- }).$mount();
-
- expect(vm.$el.tagName).toEqual('TIME');
- expect(vm.$el.getAttribute('data-original-title')).toEqual(
- formatDate('2017-05-08T14:57:39.781Z'),
- );
-
+ buildVm({
+ time: timestamp,
+ });
const timeago = getTimeago();
- expect(vm.$el.textContent.trim()).toEqual(timeago.format('2017-05-08T14:57:39.781Z'));
+ expect(vm.attributes('data-original-title')).toEqual(formatDate(timestamp));
+ expect(vm.text()).toEqual(timeago.format(timestamp));
});
it('should render provided html class', () => {
- vm = new TimeagoTooltip({
- propsData: {
- time: '2017-05-08T14:57:39.781Z',
- cssClass: 'foo',
- },
- }).$mount();
+ buildVm({
+ time: timestamp,
+ cssClass: 'foo',
+ });
- expect(vm.$el.classList.contains('foo')).toEqual(true);
+ expect(vm.classes()).toContain('foo');
});
});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
index 2f87359a4a..e76b2ca2d6 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
+import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '~/lazy_loader';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import defaultAvatarUrl from 'images/no_avatar.png';
jest.mock('images/no_avatar.png', () => 'default-avatar-url');
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
new file mode 100644
index 0000000000..7f5df02d51
--- /dev/null
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -0,0 +1,113 @@
+import _ from 'underscore';
+import { trimText } from 'helpers/text_helper';
+import { shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import { TEST_HOST } from 'spec/test_constants';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+
+describe('User Avatar Link Component', () => {
+ let wrapper;
+
+ const defaultProps = {
+ linkHref: `${TEST_HOST}/myavatarurl.com`,
+ imgSize: 99,
+ imgSrc: `${TEST_HOST}/myavatarurl.com`,
+ imgAlt: 'mydisplayname',
+ imgCssClasses: 'myextraavatarclass',
+ tooltipText: 'tooltip text',
+ tooltipPlacement: 'bottom',
+ username: 'username',
+ };
+
+ const createWrapper = props => {
+ wrapper = shallowMount(UserAvatarLink, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ sync: false,
+ attachToDocument: true,
+ });
+ };
+
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should return a defined Vue component', () => {
+ expect(wrapper.isVueInstance()).toBe(true);
+ });
+
+ it('should have user-avatar-image registered as child component', () => {
+ expect(wrapper.vm.$options.components.userAvatarImage).toBeDefined();
+ });
+
+ it('user-avatar-link should have user-avatar-image as child component', () => {
+ expect(wrapper.find(UserAvatarImage).exists()).toBe(true);
+ });
+
+ it('should render GlLink as a child element', () => {
+ const link = wrapper.find(GlLink);
+
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(defaultProps.linkHref);
+ });
+
+ it('should return necessary props as defined', () => {
+ _.each(defaultProps, (val, key) => {
+ expect(wrapper.vm[key]).toBeDefined();
+ });
+ });
+
+ describe('no username', () => {
+ beforeEach(() => {
+ createWrapper({
+ username: '',
+ });
+ });
+
+ it('should only render image tag in link', () => {
+ const childElements = wrapper.vm.$el.childNodes;
+
+ expect(wrapper.find('img')).not.toBe('null');
+
+ // Vue will render the hidden component as
+ expect(childElements[1].tagName).toBeUndefined();
+ });
+
+ it('should render avatar image tooltip', () => {
+ expect(wrapper.vm.shouldShowUsername).toBe(false);
+ expect(wrapper.vm.avatarTooltipText).toEqual(defaultProps.tooltipText);
+ });
+ });
+
+ describe('username', () => {
+ it('should not render avatar image tooltip', () => {
+ expect(wrapper.find('.js-user-avatar-image-toolip').exists()).toBe(false);
+ });
+
+ it('should render username prop in ', () => {
+ expect(trimText(wrapper.find('.js-user-avatar-link-username').text())).toEqual(
+ defaultProps.username,
+ );
+ });
+
+ it('should render text tooltip for ', () => {
+ expect(
+ wrapper.find('.js-user-avatar-link-username').attributes('data-original-title'),
+ ).toEqual(defaultProps.tooltipText);
+ });
+
+ it('should render text tooltip placement for ', () => {
+ expect(wrapper.find('.js-user-avatar-link-username').attributes('tooltip-placement')).toBe(
+ defaultProps.tooltipPlacement,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index fc2eb6329b..f2e743cc1f 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -1,5 +1,7 @@
+import { GlSkeletonLoading } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
-import { mount } from '@vue/test-utils';
+import Icon from '~/vue_shared/components/icon.vue';
const DEFAULT_PROPS = {
loaded: true,
@@ -29,7 +31,7 @@ describe('User Popover Component', () => {
describe('Empty', () => {
beforeEach(() => {
- wrapper = mount(UserPopover, {
+ wrapper = shallowMount(UserPopover, {
propsData: {
target: document.querySelector('.js-user-link'),
user: {
@@ -41,18 +43,19 @@ describe('User Popover Component', () => {
status: null,
},
},
+ attachToDocument: true,
sync: false,
});
});
it('should return skeleton loaders', () => {
- expect(wrapper.findAll('.animation-container').length).toBe(4);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(true);
});
});
describe('basic data', () => {
it('should show basic fields', () => {
- wrapper = mount(UserPopover, {
+ wrapper = shallowMount(UserPopover, {
propsData: {
...DEFAULT_PROPS,
target: document.querySelector('.js-user-link'),
@@ -66,9 +69,9 @@ describe('User Popover Component', () => {
});
it('shows icon for location', () => {
- const iconEl = wrapper.find('.js-location svg');
+ const iconEl = wrapper.find(Icon);
- expect(iconEl.find('use').element.getAttribute('xlink:href')).toContain('location');
+ expect(iconEl.props('name')).toEqual('location');
});
});
@@ -77,7 +80,7 @@ describe('User Popover Component', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
testProps.user.bio = 'Engineer';
- wrapper = mount(UserPopover, {
+ wrapper = shallowMount(UserPopover, {
propsData: {
...testProps,
target: document.querySelector('.js-user-link'),
@@ -92,7 +95,7 @@ describe('User Popover Component', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
testProps.user.organization = 'GitLab';
- wrapper = mount(UserPopover, {
+ wrapper = shallowMount(UserPopover, {
propsData: {
...testProps,
target: document.querySelector('.js-user-link'),
@@ -108,7 +111,7 @@ describe('User Popover Component', () => {
testProps.user.bio = 'Engineer';
testProps.user.organization = 'GitLab';
- wrapper = mount(UserPopover, {
+ wrapper = shallowMount(UserPopover, {
propsData: {
...DEFAULT_PROPS,
target: document.querySelector('.js-user-link'),
@@ -125,7 +128,7 @@ describe('User Popover Component', () => {
testProps.user.bio = 'Manager & Team Lead';
testProps.user.organization = 'Me & my foo
")
end
it 'uses the correct plural label' do
collection = Kaminari.paginate_array([:foo] * 23).page(1).per(10)
- expect(search_entries_info(collection, scope, 'foo')).to eq("Showing 1 - 10 of 23 #{label.pluralize} for \"foo\"")
+ expect(search_entries_info(collection, scope, 'foo')).to eq("Showing 1 - 10 of 23 #{label.pluralize} for foo
")
end
end
diff --git a/spec/helpers/services_helper_spec.rb b/spec/helpers/services_helper_spec.rb
new file mode 100644
index 0000000000..edc14f86a5
--- /dev/null
+++ b/spec/helpers/services_helper_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ServicesHelper do
+ describe 'event_action_title' do
+ it { expect(event_action_title('comment')).to eq 'Comment' }
+ it { expect(event_action_title('something')).to eq 'Something' }
+ end
+
+ describe 'event_action_description' do
+ it { expect(event_action_description('comment')).to eq 'Comment will be posted on each event' }
+ it { expect(event_action_description('something')).to eq nil }
+ end
+end
diff --git a/spec/helpers/snippets_helper_spec.rb b/spec/helpers/snippets_helper_spec.rb
index d88e151a11..6fdf4f5cfb 100644
--- a/spec/helpers/snippets_helper_spec.rb
+++ b/spec/helpers/snippets_helper_spec.rb
@@ -9,100 +9,11 @@ describe SnippetsHelper do
let_it_be(:public_personal_snippet) { create(:personal_snippet, :public) }
let_it_be(:public_project_snippet) { create(:project_snippet, :public) }
- describe '#reliable_snippet_path' do
- subject { reliable_snippet_path(snippet) }
-
- context 'personal snippets' do
- let(:snippet) { public_personal_snippet }
-
- context 'public' do
- it 'returns a full path' do
- expect(subject).to eq("/snippets/#{snippet.id}")
- end
- end
- end
-
- context 'project snippets' do
- let(:snippet) { public_project_snippet }
-
- it 'returns a full path' do
- expect(subject).to eq("/#{snippet.project.full_path}/snippets/#{snippet.id}")
- end
- end
- end
-
- describe '#reliable_snippet_url' do
- subject { reliable_snippet_url(snippet) }
-
- context 'personal snippets' do
- let(:snippet) { public_personal_snippet }
-
- context 'public' do
- it 'returns a full url' do
- expect(subject).to eq("http://test.host/snippets/#{snippet.id}")
- end
- end
- end
-
- context 'project snippets' do
- let(:snippet) { public_project_snippet }
-
- it 'returns a full url' do
- expect(subject).to eq("http://test.host/#{snippet.project.full_path}/snippets/#{snippet.id}")
- end
- end
- end
-
- describe '#reliable_raw_snippet_path' do
- subject { reliable_raw_snippet_path(snippet) }
-
- context 'personal snippets' do
- let(:snippet) { public_personal_snippet }
-
- context 'public' do
- it 'returns a full path' do
- expect(subject).to eq("/snippets/#{snippet.id}/raw")
- end
- end
- end
-
- context 'project snippets' do
- let(:snippet) { public_project_snippet }
-
- it 'returns a full path' do
- expect(subject).to eq("/#{snippet.project.full_path}/snippets/#{snippet.id}/raw")
- end
- end
- end
-
- describe '#reliable_raw_snippet_url' do
- subject { reliable_raw_snippet_url(snippet) }
-
- context 'personal snippets' do
- let(:snippet) { public_personal_snippet }
-
- context 'public' do
- it 'returns a full url' do
- expect(subject).to eq("http://test.host/snippets/#{snippet.id}/raw")
- end
- end
- end
-
- context 'project snippets' do
- let(:snippet) { public_project_snippet }
-
- it 'returns a full url' do
- expect(subject).to eq("http://test.host/#{snippet.project.full_path}/snippets/#{snippet.id}/raw")
- end
- end
- end
-
describe '#embedded_raw_snippet_button' do
subject { embedded_raw_snippet_button.to_s }
it 'returns view raw button of embedded snippets for personal snippets' do
@snippet = create(:personal_snippet, :public)
-
expect(subject).to eq(download_link("http://test.host/snippets/#{@snippet.id}/raw"))
end
@@ -216,4 +127,28 @@ describe SnippetsHelper do
end
end
end
+
+ describe '#snippet_embed_input' do
+ subject { snippet_embed_input(snippet) }
+
+ context 'with PersonalSnippet' do
+ let(:snippet) { public_personal_snippet }
+
+ it 'returns the input component' do
+ expect(subject).to eq embed_input(snippet_url(snippet))
+ end
+ end
+
+ context 'with ProjectSnippet' do
+ let(:snippet) { public_project_snippet }
+
+ it 'returns the input component' do
+ expect(subject).to eq embed_input(project_snippet_url(snippet.project, snippet))
+ end
+ end
+
+ def embed_input(url)
+ "\" autocomplete=\"off\">"
+ end
+ end
end
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index 1a176cfe96..df338fac22 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -59,29 +59,29 @@ describe VisibilityLevelHelper do
describe "#project_visibility_level_description" do
it "describes private projects" do
expect(project_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
- .to eq "Project access must be granted explicitly to each user."
+ .to eq _('Project access must be granted explicitly to each user.')
end
it "describes public projects" do
expect(project_visibility_level_description(Gitlab::VisibilityLevel::PUBLIC))
- .to eq "The project can be accessed without any authentication."
+ .to eq _('The project can be accessed without any authentication.')
end
end
describe "#snippet_visibility_level_description" do
it 'describes visibility only for me' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, personal_snippet))
- .to eq "The snippet is visible only to me."
+ .to eq _('The snippet is visible only to me.')
end
it 'describes visibility for project members' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project_snippet))
- .to eq "The snippet is visible only to project members."
+ .to eq _('The snippet is visible only to project members.')
end
it 'defaults to personal snippet' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
- .to eq "The snippet is visible only to me."
+ .to eq _('The snippet is visible only to me.')
end
end
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index bcc2bd71da..1aab01281c 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -27,7 +27,7 @@ describe WikiHelper do
let(:classes) { "btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
def expected_link(sort, direction, icon_class)
- path = "/#{project.full_path}/wikis/pages?direction=#{direction}&sort=#{sort}"
+ path = "/#{project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}"
helper.link_to(path, type: 'button', class: classes, title: 'Sort direction') do
helper.sprite_icon("sort-#{icon_class}", size: 16)
diff --git a/spec/initializers/direct_upload_support_spec.rb b/spec/initializers/direct_upload_support_spec.rb
index 4b3fe871ce..7db40f4b5a 100644
--- a/spec/initializers/direct_upload_support_spec.rb
+++ b/spec/initializers/direct_upload_support_spec.rb
@@ -56,7 +56,7 @@ describe 'Direct upload support' do
let(:connection) { nil }
it 'raises an error' do
- expect { subject }.to raise_error /are supported as a object storage provider when 'direct_upload' is used/
+ expect { subject }.to raise_error "No provider configured for '#{config_name}'. Only Google, AWS are supported."
end
end
@@ -64,7 +64,20 @@ describe 'Direct upload support' do
let(:provider) { 'Rackspace' }
it 'raises an error' do
- expect { subject }.to raise_error /are supported as a object storage provider when 'direct_upload' is used/
+ expect { subject }.to raise_error /Object storage provider '#{provider}' is not supported when 'direct_upload' is used for '#{config_name}'/
+ end
+ end
+
+ context 'when connection is omitted' do
+ let(:object_store) do
+ {
+ enabled: enabled,
+ direct_upload: direct_upload
+ }
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error /the 'connection' section is missing/
end
end
end
diff --git a/spec/javascripts/badges/components/badge_form_spec.js b/spec/javascripts/badges/components/badge_form_spec.js
index 651ac3ba3f..c7aa7fa63b 100644
--- a/spec/javascripts/badges/components/badge_form_spec.js
+++ b/spec/javascripts/badges/components/badge_form_spec.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import store from '~/badges/store';
import createEmptyBadge from '~/badges/empty_badge';
import BadgeForm from '~/badges/components/badge_form.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { DUMMY_IMAGE_URL, TEST_HOST } from '../../test_constants';
// avoid preview background process
@@ -51,13 +51,14 @@ describe('BadgeForm component', () => {
});
const sharedSubmitTests = submitAction => {
+ const nameSelector = '#badge-name';
const imageUrlSelector = '#badge-image-url';
const findImageUrlElement = () => vm.$el.querySelector(imageUrlSelector);
const linkUrlSelector = '#badge-link-url';
const findLinkUrlElement = () => vm.$el.querySelector(linkUrlSelector);
- const setValue = (inputElementSelector, url) => {
+ const setValue = (inputElementSelector, value) => {
const inputElement = vm.$el.querySelector(inputElementSelector);
- inputElement.value = url;
+ inputElement.value = value;
inputElement.dispatchEvent(new Event('input'));
};
const submitForm = () => {
@@ -82,6 +83,7 @@ describe('BadgeForm component', () => {
isSaving: false,
});
+ setValue(nameSelector, 'TestBadge');
setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
});
diff --git a/spec/javascripts/badges/components/badge_list_row_spec.js b/spec/javascripts/badges/components/badge_list_row_spec.js
index a5b47cc5f3..d143473708 100644
--- a/spec/javascripts/badges/components/badge_list_row_spec.js
+++ b/spec/javascripts/badges/components/badge_list_row_spec.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
import store from '~/badges/store';
import BadgeListRow from '~/badges/components/badge_list_row.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createDummyBadge } from '../dummy_badge';
describe('BadgeListRow component', () => {
@@ -39,6 +39,10 @@ describe('BadgeListRow component', () => {
expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
});
+ it('renders the badge name', () => {
+ expect(vm.$el).toContainText(badge.name);
+ });
+
it('renders the badge link', () => {
expect(vm.$el).toContainText(badge.linkUrl);
});
diff --git a/spec/javascripts/badges/components/badge_list_spec.js b/spec/javascripts/badges/components/badge_list_spec.js
index 2fa807657d..3af194454e 100644
--- a/spec/javascripts/badges/components/badge_list_spec.js
+++ b/spec/javascripts/badges/components/badge_list_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
import store from '~/badges/store';
import BadgeList from '~/badges/components/badge_list.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createDummyBadge } from '../dummy_badge';
describe('BadgeList component', () => {
diff --git a/spec/javascripts/badges/components/badge_settings_spec.js b/spec/javascripts/badges/components/badge_settings_spec.js
index aca26b736c..479a905661 100644
--- a/spec/javascripts/badges/components/badge_settings_spec.js
+++ b/spec/javascripts/badges/components/badge_settings_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/badges/store';
import BadgeSettings from '~/badges/components/badge_settings.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createDummyBadge } from '../dummy_badge';
describe('BadgeSettings component', () => {
diff --git a/spec/javascripts/badges/components/badge_spec.js b/spec/javascripts/badges/components/badge_spec.js
index c82a03a628..14490b1bbd 100644
--- a/spec/javascripts/badges/components/badge_spec.js
+++ b/spec/javascripts/badges/components/badge_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import Badge from '~/badges/components/badge.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants';
+import Badge from '~/badges/components/badge.vue';
describe('Badge component', () => {
const Component = Vue.extend(Badge);
diff --git a/spec/javascripts/badges/dummy_badge.js b/spec/javascripts/badges/dummy_badge.js
index f0cdaddbd3..e8a460cdc7 100644
--- a/spec/javascripts/badges/dummy_badge.js
+++ b/spec/javascripts/badges/dummy_badge.js
@@ -1,11 +1,12 @@
import _ from 'underscore';
-import { PROJECT_BADGE } from '~/badges/constants';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants';
+import { PROJECT_BADGE } from '~/badges/constants';
export const createDummyBadge = () => {
const id = _.uniqueId();
return {
id,
+ name: 'TestBadge',
imageUrl: `${TEST_HOST}/badges/${id}/image/url`,
isDeleting: false,
linkUrl: `${TEST_HOST}/badges/${id}/link/url`,
@@ -16,6 +17,7 @@ export const createDummyBadge = () => {
};
export const createDummyBadgeResponse = () => ({
+ name: 'TestBadge',
image_url: `${TEST_HOST}/badge/image/url`,
link_url: `${TEST_HOST}/badge/link/url`,
kind: PROJECT_BADGE,
diff --git a/spec/javascripts/badges/store/actions_spec.js b/spec/javascripts/badges/store/actions_spec.js
index e8d5f8c3aa..d92155d59b 100644
--- a/spec/javascripts/badges/store/actions_spec.js
+++ b/spec/javascripts/badges/store/actions_spec.js
@@ -1,10 +1,10 @@
-import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'spec/test_constants';
+import testAction from 'spec/helpers/vuex_action_helper';
+import axios from '~/lib/utils/axios_utils';
import actions, { transformBackendBadge } from '~/badges/store/actions';
import mutationTypes from '~/badges/store/mutation_types';
import createState from '~/badges/store/state';
-import { TEST_HOST } from 'spec/test_constants';
-import testAction from 'spec/helpers/vuex_action_helper';
import { createDummyBadge, createDummyBadgeResponse } from '../dummy_badge';
describe('Badges store actions', () => {
@@ -90,6 +90,7 @@ describe('Badges store actions', () => {
endpointMock.replyOnce(req => {
expect(req.data).toBe(
JSON.stringify({
+ name: 'TestBadge',
image_url: badgeInAddForm.imageUrl,
link_url: badgeInAddForm.linkUrl,
}),
@@ -114,6 +115,7 @@ describe('Badges store actions', () => {
endpointMock.replyOnce(req => {
expect(req.data).toBe(
JSON.stringify({
+ name: 'TestBadge',
image_url: badgeInAddForm.imageUrl,
link_url: badgeInAddForm.linkUrl,
}),
@@ -526,6 +528,7 @@ describe('Badges store actions', () => {
endpointMock.replyOnce(req => {
expect(req.data).toBe(
JSON.stringify({
+ name: 'TestBadge',
image_url: badgeInEditForm.imageUrl,
link_url: badgeInEditForm.linkUrl,
}),
@@ -550,6 +553,7 @@ describe('Badges store actions', () => {
endpointMock.replyOnce(req => {
expect(req.data).toBe(
JSON.stringify({
+ name: 'TestBadge',
image_url: badgeInEditForm.imageUrl,
link_url: badgeInEditForm.linkUrl,
}),
diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
index 33210794ba..0c2b7b7392 100644
--- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
+++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
@@ -1,5 +1,5 @@
-import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer';
import { FIXTURES_PATH } from 'spec/test_constants';
+import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer';
const bmprPath = `${FIXTURES_PATH}/blob/balsamiq/test.bmpr`;
diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js
index 6fa3890483..6ea097da74 100644
--- a/spec/javascripts/blob/pdf/index_spec.js
+++ b/spec/javascripts/blob/pdf/index_spec.js
@@ -1,5 +1,5 @@
-import renderPDF from '~/blob/pdf';
import { FIXTURES_PATH } from 'spec/test_constants';
+import renderPDF from '~/blob/pdf';
const testPDF = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
diff --git a/spec/javascripts/blob_edit/blob_bundle_spec.js b/spec/javascripts/blob_edit/blob_bundle_spec.js
index 48af0148e3..06c6a60315 100644
--- a/spec/javascripts/blob_edit/blob_bundle_spec.js
+++ b/spec/javascripts/blob_edit/blob_bundle_spec.js
@@ -1,5 +1,5 @@
-import blobBundle from '~/blob_edit/blob_bundle';
import $ from 'jquery';
+import blobBundle from '~/blob_edit/blob_bundle';
describe('BlobBundle', () => {
beforeEach(() => {
diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js
index 51433a5821..7236737792 100644
--- a/spec/javascripts/boards/board_card_spec.js
+++ b/spec/javascripts/boards/board_card_spec.js
@@ -13,7 +13,7 @@ import '~/boards/models/list';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue';
-import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
+import { listObj, boardsMockInterceptor, setMockEndpoints } from './mock_data';
describe('Board card', () => {
let vm;
@@ -22,8 +22,8 @@ describe('Board card', () => {
beforeEach(done => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
+ setMockEndpoints();
- gl.boardService = mockBoardService();
boardsStore.create();
boardsStore.detail.issue = {};
diff --git a/spec/javascripts/boards/board_list_common_spec.js b/spec/javascripts/boards/board_list_common_spec.js
index ada7589b79..b51a82f2a3 100644
--- a/spec/javascripts/boards/board_list_common_spec.js
+++ b/spec/javascripts/boards/board_list_common_spec.js
@@ -3,13 +3,13 @@
import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
-import axios from '~/lib/utils/axios_utils';
import Sortable from 'sortablejs';
+import axios from '~/lib/utils/axios_utils';
import BoardList from '~/boards/components/board_list.vue';
import '~/boards/models/issue';
import '~/boards/models/list';
-import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
+import { listObj, boardsMockInterceptor } from './mock_data';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
@@ -26,7 +26,6 @@ export default function createComponent({
document.body.appendChild(el);
const mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
- gl.boardService = mockBoardService();
boardsStore.create();
const BoardListComp = Vue.extend(BoardList);
diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js
index 37e96e9727..b4e1d3b97b 100644
--- a/spec/javascripts/boards/board_list_spec.js
+++ b/spec/javascripts/boards/board_list_spec.js
@@ -207,4 +207,56 @@ describe('Board list component', () => {
.catch(done.fail);
});
});
+
+ describe('max issue count warning', () => {
+ beforeEach(done => {
+ ({ mock, component } = createComponent({
+ done,
+ listProps: { type: 'closed', collapsed: true, issuesSize: 50 },
+ }));
+ });
+
+ afterEach(() => {
+ mock.restore();
+ component.$destroy();
+ });
+
+ describe('when issue count exceeds max issue count', () => {
+ it('sets background to bg-danger-100', done => {
+ component.list.issuesSize = 4;
+ component.list.maxIssueCount = 3;
+
+ Vue.nextTick(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).not.toBeNull();
+
+ done();
+ });
+ });
+ });
+
+ describe('when list issue count does NOT exceed list max issue count', () => {
+ it('does not sets background to bg-danger-100', done => {
+ component.list.issuesSize = 2;
+ component.list.maxIssueCount = 3;
+
+ Vue.nextTick(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
+
+ done();
+ });
+ });
+ });
+
+ describe('when list max issue count is 0', () => {
+ it('does not sets background to bg-danger-100', done => {
+ component.list.maxIssueCount = 0;
+
+ Vue.nextTick(() => {
+ expect(component.$el.querySelector('.bg-danger-100')).toBeNull();
+
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index 76675a78db..8e4093cc25 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -7,7 +7,7 @@ import boardNewIssue from '~/boards/components/board_new_issue.vue';
import boardsStore from '~/boards/stores/boards_store';
import '~/boards/models/list';
-import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
+import { listObj, boardsMockInterceptor } from './mock_data';
describe('Issue boards new issue form', () => {
let vm;
@@ -36,7 +36,6 @@ describe('Issue boards new issue form', () => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
- gl.boardService = mockBoardService();
boardsStore.create();
list = new List(listObj);
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
deleted file mode 100644
index 678fe5befa..0000000000
--- a/spec/javascripts/boards/boards_store_spec.js
+++ /dev/null
@@ -1,511 +0,0 @@
-/* global ListIssue */
-
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import Cookies from 'js-cookie';
-
-import '~/boards/models/label';
-import '~/boards/models/assignee';
-import '~/boards/models/issue';
-import '~/boards/models/list';
-import '~/boards/services/board_service';
-import boardsStore from '~/boards/stores/boards_store';
-import eventHub from '~/boards/eventhub';
-import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
-import waitForPromises from '../../frontend/helpers/wait_for_promises';
-
-describe('Store', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
- gl.boardService = mockBoardService();
- boardsStore.create();
-
- spyOn(gl.boardService, 'moveIssue').and.callFake(
- () =>
- new Promise(resolve => {
- resolve();
- }),
- );
-
- spyOn(gl.boardService, 'moveMultipleIssues').and.callFake(
- () =>
- new Promise(resolve => {
- resolve();
- }),
- );
-
- Cookies.set('issue_board_welcome_hidden', 'false', {
- expires: 365 * 10,
- path: '',
- });
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('starts with a blank state', () => {
- expect(boardsStore.state.lists.length).toBe(0);
- });
-
- describe('addList', () => {
- it('sorts by position', () => {
- boardsStore.addList({ position: 2 });
- boardsStore.addList({ position: 1 });
-
- expect(boardsStore.state.lists[0].position).toBe(1);
- });
- });
-
- describe('toggleFilter', () => {
- const dummyFilter = 'x=42';
- let updateTokensSpy;
-
- beforeEach(() => {
- updateTokensSpy = jasmine.createSpy('updateTokens');
- eventHub.$once('updateTokens', updateTokensSpy);
-
- // prevent using window.history
- spyOn(boardsStore, 'updateFiltersUrl').and.callFake(() => {});
- });
-
- it('adds the filter if it is not present', () => {
- boardsStore.filter.path = 'something';
-
- boardsStore.toggleFilter(dummyFilter);
-
- expect(boardsStore.filter.path).toEqual(`something&${dummyFilter}`);
- expect(updateTokensSpy).toHaveBeenCalled();
- expect(boardsStore.updateFiltersUrl).toHaveBeenCalled();
- });
-
- it('removes the filter if it is present', () => {
- boardsStore.filter.path = `something&${dummyFilter}`;
-
- boardsStore.toggleFilter(dummyFilter);
-
- expect(boardsStore.filter.path).toEqual('something');
- expect(updateTokensSpy).toHaveBeenCalled();
- expect(boardsStore.updateFiltersUrl).toHaveBeenCalled();
- });
- });
-
- describe('lists', () => {
- it('creates new list without persisting to DB', () => {
- boardsStore.addList(listObj);
-
- expect(boardsStore.state.lists.length).toBe(1);
- });
-
- it('finds list by ID', () => {
- boardsStore.addList(listObj);
- const list = boardsStore.findList('id', listObj.id);
-
- expect(list.id).toBe(listObj.id);
- });
-
- it('finds list by type', () => {
- boardsStore.addList(listObj);
- const list = boardsStore.findList('type', 'label');
-
- expect(list).toBeDefined();
- });
-
- it('finds list by label ID', () => {
- boardsStore.addList(listObj);
- const list = boardsStore.findListByLabelId(listObj.label.id);
-
- expect(list.id).toBe(listObj.id);
- });
-
- it('gets issue when new list added', done => {
- boardsStore.addList(listObj);
- const list = boardsStore.findList('id', listObj.id);
-
- expect(boardsStore.state.lists.length).toBe(1);
-
- setTimeout(() => {
- expect(list.issues.length).toBe(1);
- expect(list.issues[0].id).toBe(1);
- done();
- }, 0);
- });
-
- it('persists new list', done => {
- boardsStore.new({
- title: 'Test',
- list_type: 'label',
- label: {
- id: 1,
- title: 'Testing',
- color: 'red',
- description: 'testing;',
- },
- });
-
- expect(boardsStore.state.lists.length).toBe(1);
-
- setTimeout(() => {
- const list = boardsStore.findList('id', listObj.id);
-
- expect(list).toBeDefined();
- expect(list.id).toBe(listObj.id);
- expect(list.position).toBe(0);
- done();
- }, 0);
- });
-
- it('check for blank state adding', () => {
- expect(boardsStore.shouldAddBlankState()).toBe(true);
- });
-
- it('check for blank state not adding', () => {
- boardsStore.addList(listObj);
-
- expect(boardsStore.shouldAddBlankState()).toBe(false);
- });
-
- it('check for blank state adding when closed list exist', () => {
- boardsStore.addList({
- list_type: 'closed',
- });
-
- expect(boardsStore.shouldAddBlankState()).toBe(true);
- });
-
- it('adds the blank state', () => {
- boardsStore.addBlankState();
-
- const list = boardsStore.findList('type', 'blank', 'blank');
-
- expect(list).toBeDefined();
- });
-
- it('removes list from state', () => {
- boardsStore.addList(listObj);
-
- expect(boardsStore.state.lists.length).toBe(1);
-
- boardsStore.removeList(listObj.id, 'label');
-
- expect(boardsStore.state.lists.length).toBe(0);
- });
-
- it('moves the position of lists', () => {
- const listOne = boardsStore.addList(listObj);
- boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- boardsStore.moveList(listOne, [listObjDuplicate.id, listObj.id]);
-
- expect(listOne.position).toBe(1);
- });
-
- it('moves an issue from one list to another', done => {
- const listOne = boardsStore.addList(listObj);
- const listTwo = boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- setTimeout(() => {
- expect(listOne.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
-
- boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1));
-
- expect(listOne.issues.length).toBe(0);
- expect(listTwo.issues.length).toBe(1);
-
- done();
- }, 0);
- });
-
- it('moves an issue from backlog to a list', done => {
- const backlog = boardsStore.addList({
- ...listObj,
- list_type: 'backlog',
- });
- const listTwo = boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- setTimeout(() => {
- expect(backlog.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
-
- boardsStore.moveIssueToList(backlog, listTwo, backlog.findIssue(1));
-
- expect(backlog.issues.length).toBe(0);
- expect(listTwo.issues.length).toBe(1);
-
- done();
- }, 0);
- });
-
- it('moves issue to top of another list', done => {
- const listOne = boardsStore.addList(listObj);
- const listTwo = boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- setTimeout(() => {
- listOne.issues[0].id = 2;
-
- expect(listOne.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
-
- boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 0);
-
- expect(listOne.issues.length).toBe(0);
- expect(listTwo.issues.length).toBe(2);
- expect(listTwo.issues[0].id).toBe(2);
- expect(gl.boardService.moveIssue).toHaveBeenCalledWith(2, listOne.id, listTwo.id, null, 1);
-
- done();
- }, 0);
- });
-
- it('moves issue to bottom of another list', done => {
- const listOne = boardsStore.addList(listObj);
- const listTwo = boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- setTimeout(() => {
- listOne.issues[0].id = 2;
-
- expect(listOne.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
-
- boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 1);
-
- expect(listOne.issues.length).toBe(0);
- expect(listTwo.issues.length).toBe(2);
- expect(listTwo.issues[1].id).toBe(2);
- expect(gl.boardService.moveIssue).toHaveBeenCalledWith(2, listOne.id, listTwo.id, 1, null);
-
- done();
- }, 0);
- });
-
- it('moves issue in list', done => {
- const issue = new ListIssue({
- title: 'Testing',
- id: 2,
- iid: 2,
- confidential: false,
- labels: [],
- assignees: [],
- });
- const list = boardsStore.addList(listObj);
-
- setTimeout(() => {
- list.addIssue(issue);
-
- expect(list.issues.length).toBe(2);
-
- boardsStore.moveIssueInList(list, issue, 0, 1, [1, 2]);
-
- expect(list.issues[0].id).toBe(2);
- expect(gl.boardService.moveIssue).toHaveBeenCalledWith(2, null, null, 1, null);
-
- done();
- });
- });
- });
-
- describe('setListDetail', () => {
- it('sets the list detail', () => {
- boardsStore.detail.list = 'not a list';
-
- const dummyValue = 'new list';
- boardsStore.setListDetail(dummyValue);
-
- expect(boardsStore.detail.list).toEqual(dummyValue);
- });
- });
-
- describe('clearDetailIssue', () => {
- it('resets issue details', () => {
- boardsStore.detail.issue = 'something';
-
- boardsStore.clearDetailIssue();
-
- expect(boardsStore.detail.issue).toEqual({});
- });
- });
-
- describe('setIssueDetail', () => {
- it('sets issue details', () => {
- boardsStore.detail.issue = 'some details';
-
- const dummyValue = 'new details';
- boardsStore.setIssueDetail(dummyValue);
-
- expect(boardsStore.detail.issue).toEqual(dummyValue);
- });
- });
-
- describe('startMoving', () => {
- it('stores list and issue', () => {
- const dummyIssue = 'some issue';
- const dummyList = 'some list';
-
- boardsStore.startMoving(dummyList, dummyIssue);
-
- expect(boardsStore.moving.issue).toEqual(dummyIssue);
- expect(boardsStore.moving.list).toEqual(dummyList);
- });
- });
-
- describe('setTimeTrackingLimitToHours', () => {
- it('sets the timeTracking.LimitToHours option', () => {
- boardsStore.timeTracking.limitToHours = false;
-
- boardsStore.setTimeTrackingLimitToHours('true');
-
- expect(boardsStore.timeTracking.limitToHours).toEqual(true);
- });
- });
-
- describe('setCurrentBoard', () => {
- const dummyBoard = 'hoverboard';
-
- it('sets the current board', () => {
- const { state } = boardsStore;
- state.currentBoard = null;
-
- boardsStore.setCurrentBoard(dummyBoard);
-
- expect(state.currentBoard).toEqual(dummyBoard);
- });
- });
-
- describe('toggleMultiSelect', () => {
- let basicIssueObj;
-
- beforeAll(() => {
- basicIssueObj = { id: 987654 };
- });
-
- afterEach(() => {
- boardsStore.clearMultiSelect();
- });
-
- it('adds issue when not present', () => {
- boardsStore.toggleMultiSelect(basicIssueObj);
-
- const selectedIds = boardsStore.multiSelect.list.map(x => x.id);
-
- expect(selectedIds.includes(basicIssueObj.id)).toEqual(true);
- });
-
- it('removes issue when issue is present', () => {
- boardsStore.toggleMultiSelect(basicIssueObj);
- let selectedIds = boardsStore.multiSelect.list.map(x => x.id);
-
- expect(selectedIds.includes(basicIssueObj.id)).toEqual(true);
-
- boardsStore.toggleMultiSelect(basicIssueObj);
- selectedIds = boardsStore.multiSelect.list.map(x => x.id);
-
- expect(selectedIds.includes(basicIssueObj.id)).toEqual(false);
- });
- });
-
- describe('clearMultiSelect', () => {
- it('clears all the multi selected issues', () => {
- const issue1 = { id: 12345 };
- const issue2 = { id: 12346 };
-
- boardsStore.toggleMultiSelect(issue1);
- boardsStore.toggleMultiSelect(issue2);
-
- expect(boardsStore.multiSelect.list.length).toEqual(2);
-
- boardsStore.clearMultiSelect();
-
- expect(boardsStore.multiSelect.list.length).toEqual(0);
- });
- });
-
- describe('moveMultipleIssuesToList', () => {
- it('move issues on the new index', done => {
- const listOne = boardsStore.addList(listObj);
- const listTwo = boardsStore.addList(listObjDuplicate);
-
- expect(boardsStore.state.lists.length).toBe(2);
-
- setTimeout(() => {
- expect(listOne.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
-
- boardsStore.moveMultipleIssuesToList({
- listFrom: listOne,
- listTo: listTwo,
- issues: listOne.issues,
- newIndex: 0,
- });
-
- expect(listTwo.issues.length).toBe(1);
-
- done();
- }, 0);
- });
- });
-
- describe('moveMultipleIssuesInList', () => {
- it('moves multiple issues in list', done => {
- const issueObj = {
- title: 'Issue #1',
- id: 12345,
- iid: 2,
- confidential: false,
- labels: [],
- assignees: [],
- };
- const issue1 = new ListIssue(issueObj);
- const issue2 = new ListIssue({
- ...issueObj,
- title: 'Issue #2',
- id: 12346,
- });
-
- const list = boardsStore.addList(listObj);
-
- waitForPromises()
- .then(() => {
- list.addIssue(issue1);
- list.addIssue(issue2);
-
- expect(list.issues.length).toBe(3);
- expect(list.issues[0].id).not.toBe(issue2.id);
-
- boardsStore.moveMultipleIssuesInList({
- list,
- issues: [issue1, issue2],
- oldIndicies: [0],
- newIndex: 1,
- idArray: [1, 12345, 12346],
- });
-
- expect(list.issues[0].id).toBe(issue1.id);
-
- expect(gl.boardService.moveMultipleIssues).toHaveBeenCalledWith({
- ids: [issue1.id, issue2.id],
- fromListId: null,
- toListId: null,
- moveBeforeId: 1,
- moveAfterId: null,
- });
-
- done();
- })
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/boards/components/board_form_spec.js b/spec/javascripts/boards/components/board_form_spec.js
index e9014156a9..fd1c79d44e 100644
--- a/spec/javascripts/boards/components/board_form_spec.js
+++ b/spec/javascripts/boards/components/board_form_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import boardsStore from '~/boards/stores/boards_store';
import boardForm from '~/boards/components/board_form.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('board_form.vue', () => {
const props = {
diff --git a/spec/javascripts/boards/components/board_spec.js b/spec/javascripts/boards/components/board_spec.js
index ccb657e0df..86a2a10b7a 100644
--- a/spec/javascripts/boards/components/board_spec.js
+++ b/spec/javascripts/boards/components/board_spec.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
import Board from '~/boards/components/board';
import List from '~/boards/models/list';
-import { mockBoardService } from '../mock_data';
describe('Board component', () => {
let vm;
@@ -35,13 +34,6 @@ describe('Board component', () => {
const setUpTests = (done, opts = {}) => {
loadFixtures('boards/show.html');
- gl.boardService = mockBoardService({
- boardsEndpoint: '/',
- listsEndpoint: '/',
- bulkUpdatePath: '/',
- boardId: 1,
- });
-
createComponent(opts);
Vue.nextTick(done);
@@ -61,15 +53,6 @@ describe('Board component', () => {
};
describe('List', () => {
- beforeEach(() => {
- gl.boardService = mockBoardService({
- boardsEndpoint: '/',
- listsEndpoint: '/',
- bulkUpdatePath: '/',
- boardId: 1,
- });
- });
-
it('board is expandable when list type is closed', () => {
expect(new List({ id: 1, list_type: 'closed' }).isExpandable).toBe(true);
});
diff --git a/spec/javascripts/boards/components/boards_selector_spec.js b/spec/javascripts/boards/components/boards_selector_spec.js
index d1f36a0a65..16ec3b801c 100644
--- a/spec/javascripts/boards/components/boards_selector_spec.js
+++ b/spec/javascripts/boards/components/boards_selector_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import BoardsSelector from '~/boards/components/boards_selector.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { TEST_HOST } from 'spec/test_constants';
+import BoardsSelector from '~/boards/components/boards_selector.vue';
import boardsStore from '~/boards/stores/boards_store';
const throttleDuration = 1;
diff --git a/spec/javascripts/boards/components/issue_card_inner_scoped_label_spec.js b/spec/javascripts/boards/components/issue_card_inner_scoped_label_spec.js
index c62c5b9962..6ac51ebdb2 100644
--- a/spec/javascripts/boards/components/issue_card_inner_scoped_label_spec.js
+++ b/spec/javascripts/boards/components/issue_card_inner_scoped_label_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import IssueCardInnerScopedLabel from '~/boards/components/issue_card_inner_scoped_label.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import IssueCardInnerScopedLabel from '~/boards/components/issue_card_inner_scoped_label.vue';
describe('IssueCardInnerScopedLabel Component', () => {
let vm;
diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js
index 05e6ea1394..181e7af745 100644
--- a/spec/javascripts/boards/issue_spec.js
+++ b/spec/javascripts/boards/issue_spec.js
@@ -5,15 +5,14 @@ import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
-import '~/boards/services/board_service';
import boardsStore from '~/boards/stores/boards_store';
-import { mockBoardService } from './mock_data';
+import { setMockEndpoints } from './mock_data';
describe('Issue model', () => {
let issue;
beforeEach(() => {
- gl.boardService = mockBoardService();
+ setMockEndpoints();
boardsStore.create();
issue = new ListIssue({
diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js
index d01c37437a..c340b62730 100644
--- a/spec/javascripts/boards/list_spec.js
+++ b/spec/javascripts/boards/list_spec.js
@@ -4,15 +4,14 @@
/* global ListLabel */
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import _ from 'underscore';
+import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
-import '~/boards/services/board_service';
import boardsStore from '~/boards/stores/boards_store';
-import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
+import { listObj, listObjDuplicate, boardsMockInterceptor } from './mock_data';
describe('List model', () => {
let list;
@@ -21,9 +20,6 @@ describe('List model', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
- gl.boardService = mockBoardService({
- bulkUpdatePath: '/test/issue-boards/board/1/lists',
- });
boardsStore.create();
list = new List(listObj);
@@ -110,11 +106,11 @@ describe('List model', () => {
list.issues.push(issue);
listDup.issues.push(issue);
- spyOn(gl.boardService, 'moveIssue').and.callThrough();
+ spyOn(boardsStore, 'moveIssue').and.callThrough();
listDup.updateIssueLabel(issue, list);
- expect(gl.boardService.moveIssue).toHaveBeenCalledWith(
+ expect(boardsStore.moveIssue).toHaveBeenCalledWith(
issue.id,
list.id,
listDup.id,
@@ -172,7 +168,7 @@ describe('List model', () => {
describe('newIssue', () => {
beforeEach(() => {
- spyOn(gl.boardService, 'newIssue').and.returnValue(
+ spyOn(boardsStore, 'newIssue').and.returnValue(
Promise.resolve({
data: {
id: 42,
diff --git a/spec/javascripts/boards/mock_data.js b/spec/javascripts/boards/mock_data.js
index 41b8f567e0..fcb5d9cfa0 100644
--- a/spec/javascripts/boards/mock_data.js
+++ b/spec/javascripts/boards/mock_data.js
@@ -1,40 +1,7 @@
-import BoardService from '~/boards/services/board_service';
import boardsStore from '~/boards/stores/boards_store';
+import { listObj } from '../../frontend/boards/mock_data';
-export const boardObj = {
- id: 1,
- name: 'test',
- milestone_id: null,
-};
-
-export const listObj = {
- id: 300,
- position: 0,
- title: 'Test',
- list_type: 'label',
- weight: 3,
- label: {
- id: 5000,
- title: 'Test',
- color: 'red',
- description: 'testing;',
- textColor: 'white',
- },
-};
-
-export const listObjDuplicate = {
- id: listObj.id,
- position: 1,
- title: 'Test',
- list_type: 'label',
- weight: 3,
- label: {
- id: listObj.label.id,
- title: 'Test',
- color: 'red',
- description: 'testing;',
- },
-};
+export * from '../../frontend/boards/mock_data';
export const BoardsMockData = {
GET: {
@@ -73,7 +40,7 @@ export const boardsMockInterceptor = config => {
return [200, body];
};
-export const mockBoardService = (opts = {}) => {
+export const setMockEndpoints = (opts = {}) => {
const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/-/boards.json';
const listsEndpoint = opts.listsEndpoint || '/test/-/boards/1/lists';
const bulkUpdatePath = opts.bulkUpdatePath || '';
@@ -85,63 +52,4 @@ export const mockBoardService = (opts = {}) => {
bulkUpdatePath,
boardId,
});
-
- return new BoardService();
-};
-
-export const mockAssigneesList = [
- {
- id: 2,
- name: 'Terrell Graham',
- username: 'monserrate.gleichner',
- state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/598fd02741ac58b88854a99d16704309?s=80&d=identicon',
- web_url: 'http://127.0.0.1:3001/monserrate.gleichner',
- path: '/monserrate.gleichner',
- },
- {
- id: 12,
- name: 'Susy Johnson',
- username: 'tana_harvey',
- state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e021a7b0f3e4ae53b5068d487e68c031?s=80&d=identicon',
- web_url: 'http://127.0.0.1:3001/tana_harvey',
- path: '/tana_harvey',
- },
- {
- id: 20,
- name: 'Conchita Eichmann',
- username: 'juliana_gulgowski',
- state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/c43c506cb6fd7b37017d3b54b94aa937?s=80&d=identicon',
- web_url: 'http://127.0.0.1:3001/juliana_gulgowski',
- path: '/juliana_gulgowski',
- },
- {
- id: 6,
- name: 'Bryce Turcotte',
- username: 'melynda',
- state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/cc2518f2c6f19f8fac49e1a5ee092a9b?s=80&d=identicon',
- web_url: 'http://127.0.0.1:3001/melynda',
- path: '/melynda',
- },
- {
- id: 1,
- name: 'Administrator',
- username: 'root',
- state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- web_url: 'http://127.0.0.1:3001/root',
- path: '/root',
- },
-];
-
-export const mockMilestone = {
- id: 1,
- state: 'active',
- title: 'Milestone title',
- description: 'Harum corporis aut consequatur quae dolorem error sequi quia.',
- start_date: '2018-01-01',
- due_date: '2019-12-31',
};
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index c8d6f789ed..180ba97932 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import VariableList from '~/ci_variable_list/ci_variable_list';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+import VariableList from '~/ci_variable_list/ci_variable_list';
const HIDE_CLASS = 'hide';
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js
index 46aca2b7f0..29bdf05b8c 100644
--- a/spec/javascripts/commit/pipelines/pipelines_spec.js
+++ b/spec/javascripts/commit/pipelines/pipelines_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import Api from '~/api';
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Pipelines table in Commits and Merge requests', function() {
const jsonFixtureName = 'pipelines/pipelines.json';
@@ -83,7 +83,7 @@ describe('Pipelines table in Commits and Merge requests', function() {
};
vm.$nextTick(() => {
- vm.$el.querySelector('.js-next-button .page-link').click();
+ vm.$el.querySelector('.next-page-item').click();
expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
done();
diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
index 7aa7aa9a11..e687040ddf 100644
--- a/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
+++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import GkeMachineTypeDropdown from '~/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue';
import { createStore } from '~/create_cluster/gke_cluster/store';
import {
@@ -7,7 +8,6 @@ import {
SET_ZONE,
SET_MACHINE_TYPES,
} from '~/create_cluster/gke_cluster/store/mutation_types';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import {
selectedZoneMock,
selectedProjectMock,
diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
index 016ecfb35b..4c89124454 100644
--- a/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
+++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import GkeProjectIdDropdown from '~/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue';
import { createStore } from '~/create_cluster/gke_cluster/store';
import { SET_PROJECTS } from '~/create_cluster/gke_cluster/store/mutation_types';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { emptyProjectMock, selectedProjectMock } from '../mock_data';
import { gapi } from '../helpers';
diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
index 9cb9419e43..b2a7443422 100644
--- a/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
+++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import GkeZoneDropdown from '~/create_cluster/gke_cluster/components/gke_zone_dropdown.vue';
import { createStore } from '~/create_cluster/gke_cluster/store';
import {
@@ -6,7 +7,6 @@ import {
SET_ZONES,
SET_PROJECT_BILLING_STATUS,
} from '~/create_cluster/gke_cluster/store/mutation_types';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { selectedZoneMock, selectedProjectMock, gapiZonesResponseMock } from '../mock_data';
const componentConfig = {
diff --git a/spec/javascripts/cycle_analytics/banner_spec.js b/spec/javascripts/cycle_analytics/banner_spec.js
index 3ce2c3c4f0..86408c18dd 100644
--- a/spec/javascripts/cycle_analytics/banner_spec.js
+++ b/spec/javascripts/cycle_analytics/banner_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import banner from '~/cycle_analytics/components/banner.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import banner from '~/cycle_analytics/components/banner.vue';
describe('Cycle analytics banner', () => {
let vm;
diff --git a/spec/javascripts/cycle_analytics/total_time_component_spec.js b/spec/javascripts/cycle_analytics/total_time_component_spec.js
index 691e03cb8a..0269fc1b00 100644
--- a/spec/javascripts/cycle_analytics/total_time_component_spec.js
+++ b/spec/javascripts/cycle_analytics/total_time_component_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import component from '~/cycle_analytics/components/total_time_component.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import component from '~/cycle_analytics/components/total_time_component.vue';
describe('Total time component', () => {
let vm;
diff --git a/spec/javascripts/deploy_keys/components/app_spec.js b/spec/javascripts/deploy_keys/components/app_spec.js
index f81c0cb712..c9a9814d12 100644
--- a/spec/javascripts/deploy_keys/components/app_spec.js
+++ b/spec/javascripts/deploy_keys/components/app_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import eventHub from '~/deploy_keys/eventhub';
import deployKeysApp from '~/deploy_keys/components/app.vue';
-import { TEST_HOST } from 'spec/test_constants';
describe('Deploy keys app component', () => {
const data = getJSONFixture('deploy_keys/keys.json');
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/javascripts/diffs/components/app_spec.js
index fdf8bcee75..48e1ed18a2 100644
--- a/spec/javascripts/diffs/components/app_spec.js
+++ b/spec/javascripts/diffs/components/app_spec.js
@@ -2,10 +2,10 @@ import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
+import Mousetrap from 'mousetrap';
import App from '~/diffs/components/app.vue';
import NoChanges from '~/diffs/components/no_changes.vue';
import DiffFile from '~/diffs/components/diff_file.vue';
-import Mousetrap from 'mousetrap';
import CompareVersions from '~/diffs/components/compare_versions.vue';
import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
import CommitWidget from '~/diffs/components/commit_widget.vue';
@@ -34,14 +34,22 @@ describe('diffs/components/app', () => {
localVue,
propsData: {
endpoint: `${TEST_HOST}/diff/endpoint`,
+ endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
+ endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
projectPath: 'namespace/project',
currentUser: {},
changesEmptyStateIllustration: '',
dismissEndpoint: '',
showSuggestPopover: true,
+ useSingleDiffStyle: false,
...props,
},
store,
+ methods: {
+ isLatestVersion() {
+ return true;
+ },
+ },
});
}
@@ -59,6 +67,57 @@ describe('diffs/components/app', () => {
wrapper.destroy();
});
+ describe('fetch diff methods', () => {
+ beforeEach(() => {
+ spyOn(window, 'requestIdleCallback').and.callFake(fn => fn());
+ createComponent();
+ spyOn(wrapper.vm, 'fetchDiffFiles').and.callFake(() => Promise.resolve());
+ spyOn(wrapper.vm, 'fetchDiffFilesMeta').and.callFake(() => Promise.resolve());
+ spyOn(wrapper.vm, 'fetchDiffFilesBatch').and.callFake(() => Promise.resolve());
+ spyOn(wrapper.vm, 'setDiscussions');
+ spyOn(wrapper.vm, 'startRenderDiffsQueue');
+ });
+
+ it('calls fetchDiffFiles if diffsBatchLoad is not enabled', done => {
+ wrapper.vm.glFeatures.diffsBatchLoad = false;
+ wrapper.vm.fetchData(false);
+
+ expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
+ setTimeout(() => {
+ expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
+
+ done();
+ });
+ });
+
+ it('calls batch methods if diffsBatchLoad is enabled, and not latest version', () => {
+ wrapper.vm.glFeatures.diffsBatchLoad = true;
+ wrapper.vm.isLatestVersion = () => false;
+ wrapper.vm.fetchData(false);
+
+ expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
+ });
+ });
+
+ it('calls batch methods if diffsBatchLoad is enabled, and latest version', () => {
+ wrapper.vm.glFeatures.diffsBatchLoad = true;
+ wrapper.vm.fetchData(false);
+
+ expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
+ });
+ });
+ });
+
it('adds container-limiting classes when showFileTree is false with inline diffs', () => {
createComponent({}, ({ state }) => {
state.diffs.showTreeList = false;
@@ -93,6 +152,14 @@ describe('diffs/components/app', () => {
expect(wrapper.contains(GlLoadingIcon)).toBe(true);
});
+ it('displays loading icon on batch loading', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.isBatchLoading = true;
+ });
+
+ expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ });
+
it('displays diffs container when not loading', () => {
createComponent();
diff --git a/spec/javascripts/diffs/components/compare_versions_spec.js b/spec/javascripts/diffs/components/compare_versions_spec.js
deleted file mode 100644
index ef4bb47073..0000000000
--- a/spec/javascripts/diffs/components/compare_versions_spec.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import Vue from 'vue';
-import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
-import { createStore } from '~/mr_notes/stores';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import diffsMockData from '../mock_data/merge_request_diffs';
-import getDiffWithCommit from '../mock_data/diff_with_commit';
-
-describe('CompareVersions', () => {
- let vm;
- const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 };
-
- beforeEach(() => {
- const store = createStore();
-
- store.state.diffs.addedLines = 10;
- store.state.diffs.removedLines = 20;
- store.state.diffs.diffFiles.push('test');
-
- vm = createComponentWithStore(Vue.extend(CompareVersionsComponent), store, {
- mergeRequestDiffs: diffsMockData,
- mergeRequestDiff: diffsMockData[0],
- targetBranch,
- }).$mount();
- });
-
- describe('template', () => {
- it('should render Tree List toggle button with correct attribute values', () => {
- const treeListBtn = vm.$el.querySelector('.js-toggle-tree-list');
-
- expect(treeListBtn).not.toBeNull();
- expect(treeListBtn.dataset.originalTitle).toBe('Hide file browser');
- expect(treeListBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(treeListBtn.querySelector('svg use').getAttribute('xlink:href')).toContain(
- '#collapse-left',
- );
- });
-
- it('should render comparison dropdowns with correct values', () => {
- const sourceDropdown = vm.$el.querySelector('.mr-version-dropdown');
- const targetDropdown = vm.$el.querySelector('.mr-version-compare-dropdown');
-
- expect(sourceDropdown).not.toBeNull();
- expect(targetDropdown).not.toBeNull();
- expect(sourceDropdown.querySelector('a span').innerHTML).toContain('latest version');
- expect(targetDropdown.querySelector('a span').innerHTML).toContain(targetBranch.branchName);
- });
-
- it('should not render comparison dropdowns if no mergeRequestDiffs are specified', () => {
- vm.mergeRequestDiffs = [];
-
- vm.$nextTick(() => {
- const sourceDropdown = vm.$el.querySelector('.mr-version-dropdown');
- const targetDropdown = vm.$el.querySelector('.mr-version-compare-dropdown');
-
- expect(sourceDropdown).toBeNull();
- expect(targetDropdown).toBeNull();
- });
- });
-
- it('should render view types buttons with correct values', () => {
- const inlineBtn = vm.$el.querySelector('#inline-diff-btn');
- const parallelBtn = vm.$el.querySelector('#parallel-diff-btn');
-
- expect(inlineBtn).not.toBeNull();
- expect(parallelBtn).not.toBeNull();
- expect(inlineBtn.dataset.viewType).toEqual('inline');
- expect(parallelBtn.dataset.viewType).toEqual('parallel');
- expect(inlineBtn.innerHTML).toContain('Inline');
- expect(parallelBtn.innerHTML).toContain('Side-by-side');
- });
-
- it('adds container-limiting classes when showFileTree is false with inline diffs', () => {
- vm.isLimitedContainer = true;
-
- vm.$nextTick(() => {
- const limitedContainer = vm.$el.querySelector('.container-limited.limit-container-width');
-
- expect(limitedContainer).not.toBeNull();
- });
- });
-
- it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
- vm.isLimitedContainer = false;
-
- vm.$nextTick(() => {
- const limitedContainer = vm.$el.querySelector('.container-limited.limit-container-width');
-
- expect(limitedContainer).toBeNull();
- });
- });
- });
-
- describe('setInlineDiffViewType', () => {
- it('should persist the view type in the url', () => {
- const viewTypeBtn = vm.$el.querySelector('#inline-diff-btn');
- viewTypeBtn.click();
-
- expect(window.location.toString()).toContain('?view=inline');
- });
- });
-
- describe('setParallelDiffViewType', () => {
- it('should persist the view type in the url', () => {
- const viewTypeBtn = vm.$el.querySelector('#parallel-diff-btn');
- viewTypeBtn.click();
-
- expect(window.location.toString()).toContain('?view=parallel');
- });
- });
-
- describe('comparableDiffs', () => {
- it('should not contain the first item in the mergeRequestDiffs property', () => {
- const { comparableDiffs } = vm;
- const comparableDiffsMock = diffsMockData.slice(1);
-
- expect(comparableDiffs).toEqual(comparableDiffsMock);
- });
- });
-
- describe('baseVersionPath', () => {
- it('should be set correctly from mergeRequestDiff', () => {
- expect(vm.baseVersionPath).toEqual(vm.mergeRequestDiff.base_version_path);
- });
- });
-
- describe('commit', () => {
- beforeEach(done => {
- vm.$store.state.diffs.commit = getDiffWithCommit().commit;
- vm.mergeRequestDiffs = [];
-
- vm.$nextTick(done);
- });
-
- it('renders latest version button', () => {
- expect(vm.$el.querySelector('.js-latest-version').textContent.trim()).toBe(
- 'Show latest version',
- );
- });
-
- it('renders short commit ID', () => {
- expect(vm.$el.textContent).toContain('Viewing commit');
- expect(vm.$el.textContent).toContain(vm.commit.short_id);
- });
- });
-});
diff --git a/spec/javascripts/diffs/components/diff_expansion_cell_spec.js b/spec/javascripts/diffs/components/diff_expansion_cell_spec.js
index 63c50c09fc..e8ff677851 100644
--- a/spec/javascripts/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/javascripts/diffs/components/diff_expansion_cell_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
const EXPAND_UP_CLASS = '.js-unfold';
diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js
index 6ffdb6ba85..b4425b8e8a 100644
--- a/spec/javascripts/diffs/components/diff_file_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import DiffFileComponent from '~/diffs/components/diff_file.vue';
-import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
import { createStore } from 'ee_else_ce/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import DiffFileComponent from '~/diffs/components/diff_file.vue';
+import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
import diffFileMockDataReadable from '../mock_data/diff_file';
import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
index 6bb704658f..8d20be9971 100644
--- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import DiffLineGutterContent from '~/diffs/components/diff_line_gutter_content.vue';
import { createStore } from '~/mr_notes/stores';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import discussionsMockData from '../mock_data/diff_discussions';
import diffFileMockData from '../mock_data/diff_file';
diff --git a/spec/javascripts/diffs/components/diff_line_note_form_spec.js b/spec/javascripts/diffs/components/diff_line_note_form_spec.js
index 237cfccfa2..09263e5ce8 100644
--- a/spec/javascripts/diffs/components/diff_line_note_form_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_note_form_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
import { createStore } from '~/mr_notes/stores';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
import { noteableDataMock } from '../../notes/mock_data';
diff --git a/spec/javascripts/diffs/components/diff_table_cell_spec.js b/spec/javascripts/diffs/components/diff_table_cell_spec.js
index a5a042c577..f91e3b5680 100644
--- a/spec/javascripts/diffs/components/diff_table_cell_spec.js
+++ b/spec/javascripts/diffs/components/diff_table_cell_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import DiffTableCell from '~/diffs/components/diff_table_cell.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
describe('DiffTableCell', () => {
diff --git a/spec/javascripts/diffs/components/file_row_stats_spec.js b/spec/javascripts/diffs/components/file_row_stats_spec.js
index a8a7f3f1d8..59c5e592a5 100644
--- a/spec/javascripts/diffs/components/file_row_stats_spec.js
+++ b/spec/javascripts/diffs/components/file_row_stats_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import FileRowStats from '~/diffs/components/file_row_stats.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import FileRowStats from '~/diffs/components/file_row_stats.vue';
describe('Diff file row stats', () => {
let Component;
diff --git a/spec/javascripts/diffs/components/image_diff_overlay_spec.js b/spec/javascripts/diffs/components/image_diff_overlay_spec.js
index d76ab745fe..c2e5c6c34a 100644
--- a/spec/javascripts/diffs/components/image_diff_overlay_spec.js
+++ b/spec/javascripts/diffs/components/image_diff_overlay_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { createStore } from '~/mr_notes/stores';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { imageDiffDiscussions } from '../mock_data/diff_discussions';
describe('Diffs image diff overlay component', () => {
diff --git a/spec/javascripts/diffs/components/inline_diff_expansion_row_spec.js b/spec/javascripts/diffs/components/inline_diff_expansion_row_spec.js
index 290b3d7c80..852b8c4fbf 100644
--- a/spec/javascripts/diffs/components/inline_diff_expansion_row_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_expansion_row_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import InlineDiffExpansionRow from '~/diffs/components/inline_diff_expansion_row.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
describe('InlineDiffExpansionRow', () => {
diff --git a/spec/javascripts/diffs/components/inline_diff_table_row_spec.js b/spec/javascripts/diffs/components/inline_diff_table_row_spec.js
index 0ddffe926d..67443e9aec 100644
--- a/spec/javascripts/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_table_row_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
describe('InlineDiffTableRow', () => {
diff --git a/spec/javascripts/diffs/components/inline_diff_view_spec.js b/spec/javascripts/diffs/components/inline_diff_view_spec.js
index 486d9629e2..76d88d4d9f 100644
--- a/spec/javascripts/diffs/components/inline_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_view_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import '~/behaviors/markdown/render_gfm';
-import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
import { createStore } from 'ee_else_ce/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions';
diff --git a/spec/javascripts/diffs/components/parallel_diff_expansion_row_spec.js b/spec/javascripts/diffs/components/parallel_diff_expansion_row_spec.js
index a766ebb5ef..f6a5a1096f 100644
--- a/spec/javascripts/diffs/components/parallel_diff_expansion_row_spec.js
+++ b/spec/javascripts/diffs/components/parallel_diff_expansion_row_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import ParallelDiffExpansionRow from '~/diffs/components/parallel_diff_expansion_row.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
describe('ParallelDiffExpansionRow', () => {
diff --git a/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js b/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js
index 311eaaaa7c..32c947bbd8 100644
--- a/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/mr_notes/stores';
import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
describe('ParallelDiffTableRow', () => {
diff --git a/spec/javascripts/diffs/components/parallel_diff_view_spec.js b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
index 191313bf48..7daca25719 100644
--- a/spec/javascripts/diffs/components/parallel_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
import { createStore } from 'ee_else_ce/mr_notes/stores';
-import * as constants from '~/diffs/constants';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
+import * as constants from '~/diffs/constants';
import diffFileMockData from '../mock_data/diff_file';
describe('ParallelDiffView', () => {
diff --git a/spec/javascripts/diffs/components/settings_dropdown_spec.js b/spec/javascripts/diffs/components/settings_dropdown_spec.js
index 5031846cff..6c08474ffd 100644
--- a/spec/javascripts/diffs/components/settings_dropdown_spec.js
+++ b/spec/javascripts/diffs/components/settings_dropdown_spec.js
@@ -4,15 +4,14 @@ import diffModule from '~/diffs/store/modules';
import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('Diff settiings dropdown component', () => {
let vm;
let actions;
function createComponent(extendStore = () => {}) {
- const localVue = createLocalVue();
-
- localVue.use(Vuex);
-
const store = new Vuex.Store({
modules: {
diffs: {
@@ -26,9 +25,10 @@ describe('Diff settiings dropdown component', () => {
extendStore(store);
- vm = mount(SettingsDropdown, {
+ vm = mount(localVue.extend(SettingsDropdown), {
localVue,
store,
+ sync: false,
});
}
diff --git a/spec/javascripts/diffs/components/tree_list_spec.js b/spec/javascripts/diffs/components/tree_list_spec.js
index cd7bf6405e..0a6e433551 100644
--- a/spec/javascripts/diffs/components/tree_list_spec.js
+++ b/spec/javascripts/diffs/components/tree_list_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import TreeList from '~/diffs/components/tree_list.vue';
import createStore from '~/diffs/store/modules';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
describe('Diffs tree list component', () => {
let Component;
diff --git a/spec/javascripts/diffs/mock_data/diff_with_commit.js b/spec/javascripts/diffs/mock_data/diff_with_commit.js
index d646294ee8..c36b023906 100644
--- a/spec/javascripts/diffs/mock_data/diff_with_commit.js
+++ b/spec/javascripts/diffs/mock_data/diff_with_commit.js
@@ -1,7 +1,7 @@
-const FIXTURE = 'merge_request_diffs/with_commit.json';
+// No new code should be added to this file. Instead, modify the
+// file this one re-exports from. For more detail about why, see:
+// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-preloadFixtures(FIXTURE);
+import getDiffWithCommit from '../../../frontend/diffs/mock_data/diff_with_commit';
-export default function getDiffWithCommit() {
- return getJSONFixture(FIXTURE);
-}
+export default getDiffWithCommit;
diff --git a/spec/javascripts/diffs/mock_data/merge_request_diffs.js b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
index 4bbef14633..de29eb7e56 100644
--- a/spec/javascripts/diffs/mock_data/merge_request_diffs.js
+++ b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
@@ -1,46 +1,7 @@
-export default [
- {
- base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
- version_index: 4,
- created_at: '2018-10-23T11:49:16.611Z',
- commits_count: 4,
- latest: true,
- short_commit_sha: 'de7a8f7f',
- version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
- compare_path:
- '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=de7a8f7f20c3ea2e0bef3ba01cfd41c21f6b4995',
- },
- {
- base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
- version_index: 3,
- created_at: '2018-10-23T11:46:40.617Z',
- commits_count: 3,
- latest: false,
- short_commit_sha: 'e78fc18f',
- version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
- compare_path:
- '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=e78fc18fa37acb2185c59ca94d4a964464feb50e',
- },
- {
- base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
- version_index: 2,
- created_at: '2018-10-04T09:57:39.648Z',
- commits_count: 2,
- latest: false,
- short_commit_sha: '48da7e7e',
- version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
- compare_path:
- '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=48da7e7e9a99d41c852578bd9cb541ca4d864b3e',
- },
- {
- base_version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
- version_index: 1,
- created_at: '2018-09-25T20:30:39.493Z',
- commits_count: 1,
- latest: false,
- short_commit_sha: '47bac2ed',
- version_path: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
- compare_path:
- '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=47bac2ed972c5bee344c1cea159a22cd7f711dc0',
- },
-];
+// No new code should be added to this file. Instead, modify the
+// file this one re-exports from. For more detail about why, see:
+// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
+
+import diffsMockData from '../../../frontend/diffs/mock_data/merge_request_diffs';
+
+export default diffsMockData;
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index 874891fcc6..b23334d38d 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -1,13 +1,17 @@
import MockAdapter from 'axios-mock-adapter';
import Cookies from 'js-cookie';
+import mockDiffFile from 'spec/diffs/mock_data/diff_file';
import {
DIFF_VIEW_COOKIE_NAME,
INLINE_DIFF_VIEW_TYPE,
PARALLEL_DIFF_VIEW_TYPE,
+ DIFFS_PER_PAGE,
} from '~/diffs/constants';
import actions, {
setBaseConfig,
fetchDiffFiles,
+ fetchDiffFilesBatch,
+ fetchDiffFilesMeta,
assignDiscussionsToDiff,
removeDiscussionsFromDiff,
startRenderDiffsQueue,
@@ -42,7 +46,6 @@ import actions, {
import eventHub from '~/notes/event_hub';
import * as types from '~/diffs/store/mutation_types';
import axios from '~/lib/utils/axios_utils';
-import mockDiffFile from 'spec/diffs/mock_data/diff_file';
import testAction from '../../helpers/vuex_action_helper';
describe('DiffsStoreActions', () => {
@@ -68,18 +71,45 @@ describe('DiffsStoreActions', () => {
describe('setBaseConfig', () => {
it('should set given endpoint and project path', done => {
const endpoint = '/diffs/set/endpoint';
+ const endpointMetadata = '/diffs/set/endpoint/metadata';
+ const endpointBatch = '/diffs/set/endpoint/batch';
const projectPath = '/root/project';
const dismissEndpoint = '/-/user_callouts';
const showSuggestPopover = false;
+ const useSingleDiffStyle = false;
testAction(
setBaseConfig,
- { endpoint, projectPath, dismissEndpoint, showSuggestPopover },
- { endpoint: '', projectPath: '', dismissEndpoint: '', showSuggestPopover: true },
+ {
+ endpoint,
+ endpointBatch,
+ endpointMetadata,
+ projectPath,
+ dismissEndpoint,
+ showSuggestPopover,
+ useSingleDiffStyle,
+ },
+ {
+ endpoint: '',
+ endpointBatch: '',
+ endpointMetadata: '',
+ projectPath: '',
+ dismissEndpoint: '',
+ showSuggestPopover: true,
+ useSingleDiffStyle: true,
+ },
[
{
type: types.SET_BASE_CONFIG,
- payload: { endpoint, projectPath, dismissEndpoint, showSuggestPopover },
+ payload: {
+ endpoint,
+ endpointMetadata,
+ endpointBatch,
+ projectPath,
+ dismissEndpoint,
+ showSuggestPopover,
+ useSingleDiffStyle,
+ },
},
],
[],
@@ -114,6 +144,66 @@ describe('DiffsStoreActions', () => {
});
});
+ describe('fetchDiffFilesBatch', () => {
+ it('should fetch batch diff files', done => {
+ const endpointBatch = '/fetch/diffs_batch';
+ const mock = new MockAdapter(axios);
+ const res1 = { diff_files: [], pagination: { next_page: 2 } };
+ const res2 = { diff_files: [], pagination: {} };
+ mock
+ .onGet(endpointBatch, { params: { page: undefined, per_page: DIFFS_PER_PAGE, w: '1' } })
+ .reply(200, res1);
+ mock
+ .onGet(endpointBatch, { params: { page: 2, per_page: DIFFS_PER_PAGE, w: '1' } })
+ .reply(200, res2);
+
+ testAction(
+ fetchDiffFilesBatch,
+ {},
+ { endpointBatch },
+ [
+ { type: types.SET_BATCH_LOADING, payload: true },
+ { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
+ { type: types.SET_BATCH_LOADING, payload: false },
+ { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: [] } },
+ { type: types.SET_BATCH_LOADING, payload: false },
+ ],
+ [],
+ () => {
+ mock.restore();
+ done();
+ },
+ );
+ });
+ });
+
+ describe('fetchDiffFilesMeta', () => {
+ it('should fetch diff meta information', done => {
+ const endpointMetadata = '/fetch/diffs_meta';
+ const mock = new MockAdapter(axios);
+ const data = { diff_files: [] };
+ const res = { data };
+ mock.onGet(endpointMetadata).reply(200, res);
+
+ testAction(
+ fetchDiffFilesMeta,
+ {},
+ { endpointMetadata },
+ [
+ { type: types.SET_LOADING, payload: true },
+ { type: types.SET_LOADING, payload: false },
+ { type: types.SET_MERGE_REQUEST_DIFFS, payload: [] },
+ { type: types.SET_DIFF_DATA, payload: { data } },
+ ],
+ [],
+ () => {
+ mock.restore();
+ done();
+ },
+ );
+ });
+ });
+
describe('setHighlightedRow', () => {
it('should mark currently selected diff and set lineHash and fileHash of highlightedRow', () => {
testAction(setHighlightedRow, 'ABC_123', {}, [
diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js
index 3e033b6c9d..13f16e4f9a 100644
--- a/spec/javascripts/diffs/store/mutations_spec.js
+++ b/spec/javascripts/diffs/store/mutations_spec.js
@@ -10,11 +10,13 @@ describe('DiffsStoreMutations', () => {
const state = {};
const endpoint = '/diffs/endpoint';
const projectPath = '/root/project';
+ const useSingleDiffStyle = false;
- mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
+ mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath, useSingleDiffStyle });
expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath);
+ expect(state.useSingleDiffStyle).toEqual(useSingleDiffStyle);
});
});
@@ -28,6 +30,16 @@ describe('DiffsStoreMutations', () => {
});
});
+ describe('SET_BATCH_LOADING', () => {
+ it('should set loading state', () => {
+ const state = {};
+
+ mutations[types.SET_BATCH_LOADING](state, false);
+
+ expect(state.isBatchLoading).toEqual(false);
+ });
+ });
+
describe('SET_DIFF_DATA', () => {
it('should set diff data type properly', () => {
const state = {};
@@ -45,6 +57,23 @@ describe('DiffsStoreMutations', () => {
});
});
+ describe('SET_DIFFSET_DIFF_DATA_BATCH_DATA', () => {
+ it('should set diff data batch type properly', () => {
+ const state = { diffFiles: [] };
+ const diffMock = {
+ diff_files: [diffFileMockData],
+ };
+
+ mutations[types.SET_DIFF_DATA_BATCH](state, diffMock);
+
+ const firstLine = state.diffFiles[0].parallel_diff_lines[0];
+
+ expect(firstLine.right.text).toBeUndefined();
+ expect(state.diffFiles[0].renderIt).toEqual(true);
+ expect(state.diffFiles[0].collapsed).toEqual(false);
+ });
+ });
+
describe('SET_DIFF_VIEW_TYPE', () => {
it('should set diff view type properly', () => {
const state = {};
diff --git a/spec/javascripts/dropzone_input_spec.js b/spec/javascripts/dropzone_input_spec.js
index 125dcdb376..8d0f0d20d8 100644
--- a/spec/javascripts/dropzone_input_spec.js
+++ b/spec/javascripts/dropzone_input_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import dropzoneInput from '~/dropzone_input';
import { TEST_HOST } from 'spec/test_constants';
+import dropzoneInput from '~/dropzone_input';
const TEST_FILE = new File([], 'somefile.jpg');
TEST_FILE.upload = {};
diff --git a/spec/javascripts/environments/emtpy_state_spec.js b/spec/javascripts/environments/emtpy_state_spec.js
index 1f986d49bc..eec06a43a1 100644
--- a/spec/javascripts/environments/emtpy_state_spec.js
+++ b/spec/javascripts/environments/emtpy_state_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import emptyState from '~/environments/components/empty_state.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import emptyState from '~/environments/components/empty_state.vue';
describe('environments empty state', () => {
let vm;
diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js
index 787df757d3..a844660f7b 100644
--- a/spec/javascripts/environments/environment_actions_spec.js
+++ b/spec/javascripts/environments/environment_actions_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import eventHub from '~/environments/event_hub';
-import EnvironmentActions from '~/environments/components/environment_actions.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { TEST_HOST } from 'spec/test_constants';
+import eventHub from '~/environments/event_hub';
+import EnvironmentActions from '~/environments/components/environment_actions.vue';
describe('EnvironmentActions Component', () => {
const Component = Vue.extend(EnvironmentActions);
diff --git a/spec/javascripts/environments/environment_item_spec.js b/spec/javascripts/environments/environment_item_spec.js
deleted file mode 100644
index f9ee464812..0000000000
--- a/spec/javascripts/environments/environment_item_spec.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import 'timeago.js';
-import Vue from 'vue';
-import environmentItemComp from '~/environments/components/environment_item.vue';
-
-describe('Environment item', () => {
- let EnvironmentItem;
-
- beforeEach(() => {
- EnvironmentItem = Vue.extend(environmentItemComp);
- });
-
- describe('When item is folder', () => {
- let mockItem;
- let component;
-
- beforeEach(() => {
- mockItem = {
- name: 'review',
- folderName: 'review',
- size: 3,
- isFolder: true,
- environment_path: 'url',
- log_path: 'url',
- };
-
- component = new EnvironmentItem({
- propsData: {
- model: mockItem,
- canReadEnvironment: true,
- },
- }).$mount();
- });
-
- it('should render folder icon and name', () => {
- expect(component.$el.querySelector('.folder-name').textContent).toContain(mockItem.name);
- expect(component.$el.querySelector('.folder-icon')).toBeDefined();
- });
-
- it('should render the number of children in a badge', () => {
- expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(
- mockItem.size,
- );
- });
- });
-
- describe('when item is not folder', () => {
- let environment;
- let component;
-
- beforeEach(() => {
- environment = {
- name: 'production',
- size: 1,
- state: 'stopped',
- external_url: 'http://external.com',
- environment_type: null,
- last_deployment: {
- id: 66,
- iid: 6,
- sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
- ref: {
- name: 'master',
- ref_url: 'root/ci-folders/tree/master',
- },
- tag: true,
- 'last?': true,
- user: {
- name: 'Administrator',
- username: 'root',
- id: 1,
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- web_url: 'http://localhost:3000/root',
- },
- commit: {
- id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
- short_id: '500aabcb',
- title: 'Update .gitlab-ci.yml',
- author_name: 'Administrator',
- author_email: 'admin@example.com',
- created_at: '2016-11-07T18:28:13.000+00:00',
- message: 'Update .gitlab-ci.yml',
- author: {
- name: 'Administrator',
- username: 'root',
- id: 1,
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- web_url: 'http://localhost:3000/root',
- },
- commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
- },
- deployable: {
- id: 1279,
- name: 'deploy',
- build_path: '/root/ci-folders/builds/1279',
- retry_path: '/root/ci-folders/builds/1279/retry',
- created_at: '2016-11-29T18:11:58.430Z',
- updated_at: '2016-11-29T18:11:58.430Z',
- },
- manual_actions: [
- {
- name: 'action',
- play_path: '/play',
- },
- ],
- deployed_at: '2016-11-29T18:11:58.430Z',
- },
- has_stop_action: true,
- environment_path: 'root/ci-folders/environments/31',
- log_path: 'root/ci-folders/environments/31/logs',
- created_at: '2016-11-07T11:11:16.525Z',
- updated_at: '2016-11-10T15:55:58.778Z',
- };
-
- component = new EnvironmentItem({
- propsData: {
- model: environment,
- canReadEnvironment: true,
- },
- }).$mount();
- });
-
- it('should render environment name', () => {
- expect(component.$el.querySelector('.environment-name').textContent).toContain(
- environment.name,
- );
- });
-
- describe('With deployment', () => {
- it('should render deployment internal id', () => {
- expect(component.$el.querySelector('.deployment-column span').textContent).toContain(
- environment.last_deployment.iid,
- );
-
- expect(component.$el.querySelector('.deployment-column span').textContent).toContain('#');
- });
-
- it('should render last deployment date', () => {
- const timeagoInstance = new timeago(); // eslint-disable-line
- const formatedDate = timeagoInstance.format(environment.last_deployment.deployed_at);
-
- expect(
- component.$el.querySelector('.environment-created-date-timeago').textContent,
- ).toContain(formatedDate);
- });
-
- describe('With user information', () => {
- it('should render user avatar with link to profile', () => {
- expect(
- component.$el.querySelector('.js-deploy-user-container').getAttribute('href'),
- ).toEqual(environment.last_deployment.user.web_url);
- });
- });
-
- describe('With build url', () => {
- it('should link to build url provided', () => {
- expect(component.$el.querySelector('.build-link').getAttribute('href')).toEqual(
- environment.last_deployment.deployable.build_path,
- );
- });
-
- it('should render deployable name and id', () => {
- expect(component.$el.querySelector('.build-link').getAttribute('href')).toEqual(
- environment.last_deployment.deployable.build_path,
- );
- });
- });
-
- describe('With commit information', () => {
- it('should render commit component', () => {
- expect(component.$el.querySelector('.js-commit-component')).toBeDefined();
- });
- });
- });
-
- describe('With manual actions', () => {
- it('should render actions component', () => {
- expect(component.$el.querySelector('.js-manual-actions-container')).toBeDefined();
- });
- });
-
- describe('With external URL', () => {
- it('should render external url component', () => {
- expect(component.$el.querySelector('.js-external-url-container')).toBeDefined();
- });
- });
-
- describe('With stop action', () => {
- it('should render stop action component', () => {
- expect(component.$el.querySelector('.js-stop-component-container')).toBeDefined();
- });
- });
-
- describe('With retry action', () => {
- it('should render rollback component', () => {
- expect(component.$el.querySelector('.js-rollback-component-container')).toBeDefined();
- });
- });
- });
-});
diff --git a/spec/javascripts/environments/environment_monitoring_spec.js b/spec/javascripts/environments/environment_monitoring_spec.js
deleted file mode 100644
index f8d8223967..0000000000
--- a/spec/javascripts/environments/environment_monitoring_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import monitoringComp from '~/environments/components/environment_monitoring.vue';
-
-describe('Monitoring Component', () => {
- let MonitoringComponent;
- let component;
-
- const monitoringUrl = 'https://gitlab.com';
-
- beforeEach(() => {
- MonitoringComponent = Vue.extend(monitoringComp);
-
- component = new MonitoringComponent({
- propsData: {
- monitoringUrl,
- },
- }).$mount();
- });
-
- describe('computed', () => {
- it('title', () => {
- expect(component.title).toEqual('Monitoring');
- });
- });
-
- it('should render a link to environment monitoring page', () => {
- expect(component.$el.getAttribute('href')).toEqual(monitoringUrl);
- expect(component.$el.querySelector('.fa-area-chart')).toBeDefined();
- expect(component.$el.getAttribute('data-original-title')).toEqual('Monitoring');
- expect(component.$el.getAttribute('aria-label')).toEqual('Monitoring');
- });
-});
diff --git a/spec/javascripts/environments/environment_stop_spec.js b/spec/javascripts/environments/environment_stop_spec.js
deleted file mode 100644
index 4d9caa5756..0000000000
--- a/spec/javascripts/environments/environment_stop_spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Vue from 'vue';
-import stopComp from '~/environments/components/environment_stop.vue';
-
-describe('Stop Component', () => {
- let StopComponent;
- let component;
-
- beforeEach(() => {
- StopComponent = Vue.extend(stopComp);
- spyOn(window, 'confirm').and.returnValue(true);
-
- component = new StopComponent({
- propsData: {
- environment: {},
- },
- }).$mount();
- });
-
- it('should render a button to stop the environment', () => {
- expect(component.$el.tagName).toEqual('BUTTON');
- expect(component.$el.getAttribute('data-original-title')).toEqual('Stop environment');
- });
-});
diff --git a/spec/javascripts/environments/environment_terminal_button_spec.js b/spec/javascripts/environments/environment_terminal_button_spec.js
deleted file mode 100644
index fc98e656ef..0000000000
--- a/spec/javascripts/environments/environment_terminal_button_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import Vue from 'vue';
-import terminalComp from '~/environments/components/environment_terminal_button.vue';
-
-describe('Stop Component', () => {
- let component;
- const terminalPath = '/path';
-
- const mountWithProps = props => {
- const TerminalComponent = Vue.extend(terminalComp);
- component = new TerminalComponent({
- propsData: props,
- }).$mount();
- };
-
- beforeEach(() => {
- mountWithProps({ terminalPath });
- });
-
- describe('computed', () => {
- it('title', () => {
- expect(component.title).toEqual('Terminal');
- });
- });
-
- it('should render a link to open a web terminal with the provided path', () => {
- expect(component.$el.tagName).toEqual('A');
- expect(component.$el.getAttribute('data-original-title')).toEqual('Terminal');
- expect(component.$el.getAttribute('aria-label')).toEqual('Terminal');
- expect(component.$el.getAttribute('href')).toEqual(terminalPath);
- });
-
- it('should render a non-disabled button', () => {
- expect(component.$el.classList).not.toContain('disabled');
- });
-});
diff --git a/spec/javascripts/environments/environments_app_spec.js b/spec/javascripts/environments/environments_app_spec.js
index 0dcd8868ab..75526c2ba7 100644
--- a/spec/javascripts/environments/environments_app_spec.js
+++ b/spec/javascripts/environments/environments_app_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import environmentsComponent from '~/environments/components/environments_app.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { environment, folder } from './mock_data';
describe('Environment', () => {
@@ -10,7 +10,6 @@ describe('Environment', () => {
endpoint: 'environments.json',
canCreateEnvironment: true,
canReadEnvironment: true,
- cssContainerClass: 'container',
newEnvironmentPath: 'environments/new',
helpPagePath: 'help',
canaryDeploymentFeatureId: 'canary_deployment',
@@ -93,13 +92,13 @@ describe('Environment', () => {
describe('pagination', () => {
it('should render pagination', () => {
- expect(component.$el.querySelectorAll('.gl-pagination li').length).toEqual(5);
+ expect(component.$el.querySelectorAll('.gl-pagination li').length).toEqual(9);
});
it('should make an API request when page is clicked', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
- component.$el.querySelector('.gl-pagination li:nth-child(5) .page-link').click();
+ component.$el.querySelector('.gl-pagination li:nth-child(3) .page-link').click();
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', page: '2' });
done();
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index f1c323df4b..6530201240 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { removeBreakLine, removeWhitespace } from 'spec/helpers/text_helper';
+import axios from '~/lib/utils/axios_utils';
+import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
import { environmentsList } from '../mock_data';
describe('Environments Folder View', () => {
@@ -115,7 +115,9 @@ describe('Environments Folder View', () => {
it('should make an API request when changing page', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
- component.$el.querySelector('.gl-pagination .js-last-button .page-link').click();
+ component.$el
+ .querySelector('.gl-pagination .page-item:nth-last-of-type(2) .page-link')
+ .click();
expect(component.updateContent).toHaveBeenCalledWith({
scope: component.scope,
diff --git a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
index e5795d4cbb..ba35f7bf7c 100644
--- a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
+++ b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
@@ -1,11 +1,10 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
import axios from '~/lib/utils/axios_utils';
import { getSelector, dismiss, inserted } from '~/feature_highlight/feature_highlight_helper';
import { togglePopover } from '~/shared/popover';
-import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
-
describe('feature highlight helper', () => {
describe('getSelector', () => {
it('returns js-feature-highlight selector', () => {
diff --git a/spec/javascripts/feature_highlight/feature_highlight_spec.js b/spec/javascripts/feature_highlight/feature_highlight_spec.js
index 0a9fba789c..40ac4bbb6a 100644
--- a/spec/javascripts/feature_highlight/feature_highlight_spec.js
+++ b/spec/javascripts/feature_highlight/feature_highlight_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
+import MockAdapter from 'axios-mock-adapter';
import * as featureHighlight from '~/feature_highlight/feature_highlight';
import * as popover from '~/shared/popover';
import axios from '~/lib/utils/axios_utils';
-import MockAdapter from 'axios-mock-adapter';
describe('feature highlight', () => {
beforeEach(() => {
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
index 10d844fd94..5863005de1 100644
--- a/spec/javascripts/filtered_search/visual_token_value_spec.js
+++ b/spec/javascripts/filtered_search/visual_token_value_spec.js
@@ -1,5 +1,5 @@
-import VisualTokenValue from '~/filtered_search/visual_token_value';
import _ from 'underscore';
+import VisualTokenValue from '~/filtered_search/visual_token_value';
import AjaxCache from '~/lib/utils/ajax_cache';
import UsersCache from '~/lib/utils/users_cache';
import DropdownUtils from '~/filtered_search//dropdown_utils';
diff --git a/spec/javascripts/frequent_items/components/app_spec.js b/spec/javascripts/frequent_items/components/app_spec.js
index da0427d650..b293ed541f 100644
--- a/spec/javascripts/frequent_items/components/app_spec.js
+++ b/spec/javascripts/frequent_items/components/app_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import axios from '~/lib/utils/axios_utils';
import appComponent from '~/frequent_items/components/app.vue';
import eventHub from '~/frequent_items/event_hub';
import store from '~/frequent_items/store';
import { FREQUENT_ITEMS, HOUR_IN_MS } from '~/frequent_items/constants';
import { getTopFrequentItems } from '~/frequent_items/utils';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { currentSession, mockFrequentProjects, mockSearchedProjects } from '../mock_data';
let session;
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
index dce8e3be14..9bf3e02557 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,53 +1,51 @@
-import Vue from 'vue';
-import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { trimText } from 'spec/helpers/text_helper';
+import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
import { mockProject } from '../mock_data'; // can also use 'mockGroup', but not useful to test here
-const createComponent = () => {
- const Component = Vue.extend(frequentItemsListItemComponent);
-
- return shallowMount(Component, {
- propsData: {
- itemId: mockProject.id,
- itemName: mockProject.name,
- namespace: mockProject.namespace,
- webUrl: mockProject.webUrl,
- avatarUrl: mockProject.avatarUrl,
- },
- });
-};
+const localVue = createLocalVue();
describe('FrequentItemsListItemComponent', () => {
let wrapper;
- let vm;
- beforeEach(() => {
- wrapper = createComponent();
-
- ({ vm } = wrapper);
- });
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(localVue.extend(frequentItemsListItemComponent), {
+ propsData: {
+ itemId: mockProject.id,
+ itemName: mockProject.name,
+ namespace: mockProject.namespace,
+ webUrl: mockProject.webUrl,
+ avatarUrl: mockProject.avatarUrl,
+ ...props,
+ },
+ sync: false,
+ localVue,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
describe('computed', () => {
describe('hasAvatar', () => {
it('should return `true` or `false` if whether avatar is present or not', () => {
- wrapper.setProps({ avatarUrl: 'path/to/avatar.png' });
+ createComponent({ avatarUrl: 'path/to/avatar.png' });
- expect(vm.hasAvatar).toBe(true);
+ expect(wrapper.vm.hasAvatar).toBe(true);
+ });
- wrapper.setProps({ avatarUrl: null });
+ it('should return `false` if avatar is not present', () => {
+ createComponent({ avatarUrl: null });
- expect(vm.hasAvatar).toBe(false);
+ expect(wrapper.vm.hasAvatar).toBe(false);
});
});
describe('highlightedItemName', () => {
it('should enclose part of project name in & which matches with `matcher` prop', () => {
- wrapper.setProps({ matcher: 'lab' });
+ createComponent({ matcher: 'lab' });
expect(wrapper.find('.js-frequent-items-item-title').html()).toContain(
'Lab',
@@ -55,7 +53,7 @@ describe('FrequentItemsListItemComponent', () => {
});
it('should return project name as it is if `matcher` is not available', () => {
- wrapper.setProps({ matcher: null });
+ createComponent({ matcher: null });
expect(trimText(wrapper.find('.js-frequent-items-item-title').text())).toBe(
mockProject.name,
@@ -65,13 +63,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('truncatedNamespace', () => {
it('should truncate project name from namespace string', () => {
- wrapper.setProps({ namespace: 'platform / nokia-3310' });
+ createComponent({ namespace: 'platform / nokia-3310' });
expect(trimText(wrapper.find('.js-frequent-items-item-namespace').text())).toBe('platform');
});
it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
- wrapper.setProps({
+ createComponent({
namespace: 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310',
});
@@ -84,6 +82,8 @@ describe('FrequentItemsListItemComponent', () => {
describe('template', () => {
it('should render component element', () => {
+ createComponent();
+
expect(wrapper.classes()).toContain('frequent-items-list-item-container');
expect(wrapper.findAll('a').length).toBe(1);
expect(wrapper.findAll('.frequent-items-item-avatar-container').length).toBe(1);
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
index 8518a681a2..3fcd79480c 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
import { mockFrequentProjects } from '../mock_data';
const createComponent = (namespace = 'projects') => {
diff --git a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
index ddbbc5c2d2..be11af8428 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
@@ -1,13 +1,15 @@
-import Vue from 'vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue';
import eventHub from '~/frequent_items/event_hub';
-import { shallowMount } from '@vue/test-utils';
-const createComponent = (namespace = 'projects') => {
- const Component = Vue.extend(searchComponent);
+const localVue = createLocalVue();
- return shallowMount(Component, { propsData: { namespace } });
-};
+const createComponent = (namespace = 'projects') =>
+ shallowMount(localVue.extend(searchComponent), {
+ propsData: { namespace },
+ localVue,
+ sync: false,
+ });
describe('FrequentItemsSearchInputComponent', () => {
let wrapper;
@@ -40,7 +42,7 @@ describe('FrequentItemsSearchInputComponent', () => {
spyOn(eventHub, '$on');
const vmX = createComponent().vm;
- Vue.nextTick(() => {
+ localVue.nextTick(() => {
expect(eventHub.$on).toHaveBeenCalledWith(
`${vmX.namespace}-dropdownOpen`,
jasmine.any(Function),
@@ -58,7 +60,7 @@ describe('FrequentItemsSearchInputComponent', () => {
vmX.$mount();
vmX.$destroy();
- Vue.nextTick(() => {
+ localVue.nextTick(() => {
expect(eventHub.$off).toHaveBeenCalledWith(
`${vmX.namespace}-dropdownOpen`,
jasmine.any(Function),
diff --git a/spec/javascripts/frequent_items/mock_data.js b/spec/javascripts/frequent_items/mock_data.js
index 7f7d7b1cdb..419f70e41a 100644
--- a/spec/javascripts/frequent_items/mock_data.js
+++ b/spec/javascripts/frequent_items/mock_data.js
@@ -68,7 +68,7 @@ export const mockFrequentGroups = [
},
];
-export const mockSearchedGroups = { data: [mockRawGroup] };
+export const mockSearchedGroups = [mockRawGroup];
export const mockProcessedSearchedGroups = [mockGroup];
export const mockProject = {
diff --git a/spec/javascripts/gpg_badges_spec.js b/spec/javascripts/gpg_badges_spec.js
index e73f6d3909..4731484e02 100644
--- a/spec/javascripts/gpg_badges_spec.js
+++ b/spec/javascripts/gpg_badges_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import GpgBadges from '~/gpg_badges';
-import { TEST_HOST } from 'spec/test_constants';
describe('GpgBadges', () => {
let mock;
diff --git a/spec/javascripts/groups/components/group_item_spec.js b/spec/javascripts/groups/components/group_item_spec.js
index cc88a7ac6c..39575ee9f9 100644
--- a/spec/javascripts/groups/components/group_item_spec.js
+++ b/spec/javascripts/groups/components/group_item_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import groupItemComponent from '~/groups/components/group_item.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import eventHub from '~/groups/event_hub';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockParentGroupItem, mockChildren } from '../mock_data';
const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren[0]) => {
diff --git a/spec/javascripts/groups/components/groups_spec.js b/spec/javascripts/groups/components/groups_spec.js
index 6ba4fe23a6..8423467742 100644
--- a/spec/javascripts/groups/components/groups_spec.js
+++ b/spec/javascripts/groups/components/groups_spec.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import groupsComponent from '~/groups/components/groups.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue';
import eventHub from '~/groups/event_hub';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockGroups, mockPageInfo } from '../mock_data';
const createComponent = (searchEmpty = false) => {
diff --git a/spec/javascripts/groups/components/item_actions_spec.js b/spec/javascripts/groups/components/item_actions_spec.js
index 3f66e7fd6f..9a9d6208ea 100644
--- a/spec/javascripts/groups/components/item_actions_spec.js
+++ b/spec/javascripts/groups/components/item_actions_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import itemActionsComponent from '~/groups/components/item_actions.vue';
import eventHub from '~/groups/event_hub';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockParentGroupItem, mockChildren } from '../mock_data';
const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren[0]) => {
diff --git a/spec/javascripts/groups/components/item_caret_spec.js b/spec/javascripts/groups/components/item_caret_spec.js
index 6e430dbcdb..0eb56abbd6 100644
--- a/spec/javascripts/groups/components/item_caret_spec.js
+++ b/spec/javascripts/groups/components/item_caret_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import itemCaretComponent from '~/groups/components/item_caret.vue';
-
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import itemCaretComponent from '~/groups/components/item_caret.vue';
const createComponent = (isGroupOpen = false) => {
const Component = Vue.extend(itemCaretComponent);
diff --git a/spec/javascripts/groups/components/item_stats_spec.js b/spec/javascripts/groups/components/item_stats_spec.js
index b2441babf3..13d17b87d7 100644
--- a/spec/javascripts/groups/components/item_stats_spec.js
+++ b/spec/javascripts/groups/components/item_stats_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import itemStatsComponent from '~/groups/components/item_stats.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import itemStatsComponent from '~/groups/components/item_stats.vue';
import {
mockParentGroupItem,
ITEM_TYPE,
diff --git a/spec/javascripts/groups/components/item_stats_value_spec.js b/spec/javascripts/groups/components/item_stats_value_spec.js
index ea8edcf49c..ff4e781ce1 100644
--- a/spec/javascripts/groups/components/item_stats_value_spec.js
+++ b/spec/javascripts/groups/components/item_stats_value_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import itemStatsValueComponent from '~/groups/components/item_stats_value.vue';
-
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import itemStatsValueComponent from '~/groups/components/item_stats_value.vue';
const createComponent = ({ title, cssClass, iconName, tooltipPlacement, value }) => {
const Component = Vue.extend(itemStatsValueComponent);
diff --git a/spec/javascripts/groups/components/item_type_icon_spec.js b/spec/javascripts/groups/components/item_type_icon_spec.js
index 7310851222..321712e54a 100644
--- a/spec/javascripts/groups/components/item_type_icon_spec.js
+++ b/spec/javascripts/groups/components/item_type_icon_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import itemTypeIconComponent from '~/groups/components/item_type_icon.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import itemTypeIconComponent from '~/groups/components/item_type_icon.vue';
import { ITEM_TYPE } from '../mock_data';
const createComponent = (itemType = ITEM_TYPE.GROUP, isGroupOpen = false) => {
diff --git a/spec/javascripts/helpers/init_vue_mr_page_helper.js b/spec/javascripts/helpers/init_vue_mr_page_helper.js
index fc4288eb15..3fa29cb913 100644
--- a/spec/javascripts/helpers/init_vue_mr_page_helper.js
+++ b/spec/javascripts/helpers/init_vue_mr_page_helper.js
@@ -1,6 +1,6 @@
+import MockAdapter from 'axios-mock-adapter';
import initMRPage from '~/mr_notes/index';
import axios from '~/lib/utils/axios_utils';
-import MockAdapter from 'axios-mock-adapter';
import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
import diffFileMockData from '../diffs/mock_data/diff_file';
diff --git a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
index a3db3ee1b1..d02d8fa025 100644
--- a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { projectData, branches } from 'spec/ide/mock_data';
import { createStore } from '~/ide/stores';
import commitActions from '~/ide/components/commit_sidebar/actions.vue';
import consts from '~/ide/stores/modules/commit/constants';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { projectData, branches } from 'spec/ide/mock_data';
const ACTION_UPDATE_COMMIT_ACTION = 'commit/updateCommitAction';
diff --git a/spec/javascripts/ide/components/commit_sidebar/form_spec.js b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
index b7a7afe4db..fdbabf84e2 100644
--- a/spec/javascripts/ide/components/commit_sidebar/form_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
-import store from '~/ide/stores';
-import CommitForm from '~/ide/components/commit_sidebar/form.vue';
-import { activityBarViews } from '~/ide/constants';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
import { projectData } from 'spec/ide/mock_data';
+import store from '~/ide/stores';
+import CommitForm from '~/ide/components/commit_sidebar/form.vue';
+import { activityBarViews } from '~/ide/constants';
import { resetStore } from '../../helpers';
describe('IDE commit form', () => {
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
index 3c7d6192e2..6eb912127d 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import listCollapsed from '~/ide/components/commit_sidebar/list_collapsed.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file } from '../../helpers';
import { removeWhitespace } from '../../../helpers/text_helper';
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
index c1dcd4928a..caf06b5e1d 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
+import { trimText } from 'spec/helpers/text_helper';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import listItem from '~/ide/components/commit_sidebar/list_item.vue';
import router from '~/ide/ide_router';
-import { trimText } from 'spec/helpers/text_helper';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file, resetStore } from '../../helpers';
describe('Multi-file editor commit sidebar list item', () => {
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_spec.js
index b786be5501..81120f6d27 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import commitSidebarList from '~/ide/components/commit_sidebar/list.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file, resetStore } from '../../helpers';
describe('Multi-file editor commit sidebar list', () => {
diff --git a/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js b/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
index af67991ead..53508f52b2 100644
--- a/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
import createComponent from 'spec/helpers/vue_mount_component_helper';
+import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
describe('IDE commit message field', () => {
const Component = Vue.extend(CommitMessageField);
diff --git a/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
index 5f2db69524..02caf689c5 100644
--- a/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import store from '~/ide/stores';
-import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { projectData, branches } from 'spec/ide/mock_data';
import { resetStore } from 'spec/ide/helpers';
+import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
+import store from '~/ide/stores';
import consts from '../../../../../app/assets/javascripts/ide/stores/modules/commit/constants';
describe('create new MR checkbox', () => {
diff --git a/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js b/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
index db1988be3e..b30f0e6822 100644
--- a/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import store from '~/ide/stores';
-import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from 'spec/ide/helpers';
+import store from '~/ide/stores';
+import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
describe('IDE commit sidebar radio group', () => {
let vm;
diff --git a/spec/javascripts/ide/components/file_row_extra_spec.js b/spec/javascripts/ide/components/file_row_extra_spec.js
index 86146fcef6..4c2f29f55d 100644
--- a/spec/javascripts/ide/components/file_row_extra_spec.js
+++ b/spec/javascripts/ide/components/file_row_extra_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import { createStore } from '~/ide/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { createStore } from '~/ide/stores';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import { file, resetStore } from '../helpers';
diff --git a/spec/javascripts/ide/components/file_templates/bar_spec.js b/spec/javascripts/ide/components/file_templates/bar_spec.js
index a688f7f69a..5399ada94a 100644
--- a/spec/javascripts/ide/components/file_templates/bar_spec.js
+++ b/spec/javascripts/ide/components/file_templates/bar_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/ide/stores';
import Bar from '~/ide/components/file_templates/bar.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore, file } from '../../helpers';
describe('IDE file templates bar component', () => {
diff --git a/spec/javascripts/ide/components/ide_side_bar_spec.js b/spec/javascripts/ide/components/ide_side_bar_spec.js
index 20ee20bc1d..a2d15462ac 100644
--- a/spec/javascripts/ide/components/ide_side_bar_spec.js
+++ b/spec/javascripts/ide/components/ide_side_bar_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import ideSidebar from '~/ide/components/ide_side_bar.vue';
import { activityBarViews } from '~/ide/constants';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
index de4becec1c..048db4a753 100644
--- a/spec/javascripts/ide/components/ide_spec.js
+++ b/spec/javascripts/ide/components/ide_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import ide from '~/ide/components/ide.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file, resetStore } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/javascripts/ide/components/ide_status_bar_spec.js b/spec/javascripts/ide/components/ide_status_bar_spec.js
index bb8fb74c06..69f163574f 100644
--- a/spec/javascripts/ide/components/ide_status_bar_spec.js
+++ b/spec/javascripts/ide/components/ide_status_bar_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import ideStatusBar from '~/ide/components/ide_status_bar.vue';
import { rightSidebarViews } from '~/ide/constants';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/javascripts/ide/components/nav_dropdown_button_spec.js b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
index 19b0071567..0d63869fba 100644
--- a/spec/javascripts/ide/components/nav_dropdown_button_spec.js
+++ b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
-import store from '~/ide/stores';
import { trimText } from 'spec/helpers/text_helper';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
+import store from '~/ide/stores';
import { resetStore } from '../helpers';
describe('NavDropdown', () => {
diff --git a/spec/javascripts/ide/components/nav_dropdown_spec.js b/spec/javascripts/ide/components/nav_dropdown_spec.js
index af6665bcd6..fe1d0ca371 100644
--- a/spec/javascripts/ide/components/nav_dropdown_spec.js
+++ b/spec/javascripts/ide/components/nav_dropdown_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import NavDropdown from '~/ide/components/nav_dropdown.vue';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
describe('IDE NavDropdown', () => {
const Component = Vue.extend(NavDropdown);
diff --git a/spec/javascripts/ide/components/new_dropdown/index_spec.js b/spec/javascripts/ide/components/new_dropdown/index_spec.js
index aaebe88f31..03afe997fe 100644
--- a/spec/javascripts/ide/components/new_dropdown/index_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/index_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import newDropdown from '~/ide/components/new_dropdown/index.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../../helpers';
describe('new dropdown component', () => {
diff --git a/spec/javascripts/ide/components/new_dropdown/modal_spec.js b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
index 0556feae46..a1c00e9992 100644
--- a/spec/javascripts/ide/components/new_dropdown/modal_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { createStore } from '~/ide/stores';
import modal from '~/ide/components/new_dropdown/modal.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
describe('new file modal component', () => {
const Component = Vue.extend(modal);
diff --git a/spec/javascripts/ide/components/new_dropdown/upload_spec.js b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
index d19af6af2d..4ebd097783 100644
--- a/spec/javascripts/ide/components/new_dropdown/upload_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import upload from '~/ide/components/new_dropdown/upload.vue';
import createComponent from 'spec/helpers/vue_mount_component_helper';
+import upload from '~/ide/components/new_dropdown/upload.vue';
describe('new dropdown upload', () => {
let vm;
diff --git a/spec/javascripts/ide/components/repo_commit_section_spec.js b/spec/javascripts/ide/components/repo_commit_section_spec.js
index 6c726c1e15..917eb1438b 100644
--- a/spec/javascripts/ide/components/repo_commit_section_spec.js
+++ b/spec/javascripts/ide/components/repo_commit_section_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import router from '~/ide/ide_router';
import repoCommitSection from '~/ide/components/repo_commit_section.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file, resetStore } from '../helpers';
describe('RepoCommitSection', () => {
diff --git a/spec/javascripts/ide/components/shared/tokened_input_spec.js b/spec/javascripts/ide/components/shared/tokened_input_spec.js
index b09bf76054..885fd97665 100644
--- a/spec/javascripts/ide/components/shared/tokened_input_spec.js
+++ b/spec/javascripts/ide/components/shared/tokened_input_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import TokenedInput from '~/ide/components/shared/tokened_input.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import TokenedInput from '~/ide/components/shared/tokened_input.vue';
const TEST_PLACEHOLDER = 'Searching in test';
const TEST_TOKENS = [
diff --git a/spec/javascripts/ide/helpers.js b/spec/javascripts/ide/helpers.js
index 7e10774734..2c52780f31 100644
--- a/spec/javascripts/ide/helpers.js
+++ b/spec/javascripts/ide/helpers.js
@@ -1,54 +1 @@
-import * as pathUtils from 'path';
-import { decorateData } from '~/ide/stores/utils';
-import state from '~/ide/stores/state';
-import commitState from '~/ide/stores/modules/commit/state';
-import mergeRequestsState from '~/ide/stores/modules/merge_requests/state';
-import pipelinesState from '~/ide/stores/modules/pipelines/state';
-import branchesState from '~/ide/stores/modules/branches/state';
-import fileTemplatesState from '~/ide/stores/modules/file_templates/state';
-import paneState from '~/ide/stores/modules/pane/state';
-
-export const resetStore = store => {
- const newState = {
- ...state(),
- commit: commitState(),
- mergeRequests: mergeRequestsState(),
- pipelines: pipelinesState(),
- branches: branchesState(),
- fileTemplates: fileTemplatesState(),
- rightPane: paneState(),
- };
- store.replaceState(newState);
-};
-
-export const file = (name = 'name', id = name, type = '', parent = null) =>
- decorateData({
- id,
- type,
- icon: 'icon',
- url: 'url',
- name,
- path: parent ? `${parent.path}/${name}` : name,
- parentPath: parent ? parent.path : '',
- lastCommit: {},
- });
-
-export const createEntriesFromPaths = paths =>
- paths
- .map(path => ({
- name: pathUtils.basename(path),
- dir: pathUtils.dirname(path),
- ext: pathUtils.extname(path),
- }))
- .reduce((entries, path, idx) => {
- const { name } = path;
- const parent = path.dir ? entries[path.dir] : null;
- const type = path.ext ? 'blob' : 'tree';
-
- const entry = file(name, (idx + 1).toString(), type, parent);
-
- return {
- [entry.path]: entry,
- ...entries,
- };
- }, {});
+export * from '../../frontend/ide/helpers';
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index 7e77b859fd..0ee114cb70 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -1,3 +1,4 @@
+import MockAdapter from 'axios-mock-adapter';
import actions, {
stageAllChanges,
unstageAllChanges,
@@ -11,6 +12,7 @@ import actions, {
renameEntry,
getBranchData,
createTempEntry,
+ discardAllChanges,
} from '~/ide/stores/actions';
import axios from '~/lib/utils/axios_utils';
import { createStore } from '~/ide/stores';
@@ -18,7 +20,6 @@ import * as types from '~/ide/stores/mutation_types';
import router from '~/ide/ide_router';
import { resetStore, file } from '../helpers';
import testAction from '../../helpers/vuex_action_helper';
-import MockAdapter from 'axios-mock-adapter';
import eventHub from '~/ide/eventhub';
const store = createStore();
@@ -60,8 +61,9 @@ describe('Multi-file store actions', () => {
});
describe('discardAllChanges', () => {
+ let f;
beforeEach(() => {
- const f = file('discardAll');
+ f = file('discardAll');
f.changed = true;
store.state.openFiles.push(f);
@@ -89,6 +91,59 @@ describe('Multi-file store actions', () => {
.then(done)
.catch(done.fail);
});
+
+ it('closes the temp file and deletes it if it was open', done => {
+ f.tempFile = true;
+
+ testAction(
+ discardAllChanges,
+ undefined,
+ store.state,
+ [{ type: types.REMOVE_ALL_CHANGES_FILES }],
+ [
+ { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
+ { type: 'deleteEntry', payload: 'discardAll' },
+ ],
+ done,
+ );
+ });
+
+ it('renames the file to its original name and closes it if it was open', done => {
+ Object.assign(f, {
+ prevPath: 'parent/path/old_name',
+ prevName: 'old_name',
+ prevParentPath: 'parent/path',
+ });
+
+ testAction(
+ discardAllChanges,
+ undefined,
+ store.state,
+ [{ type: types.REMOVE_ALL_CHANGES_FILES }],
+ [
+ { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
+ {
+ type: 'renameEntry',
+ payload: { path: 'discardAll', name: 'old_name', parentPath: 'parent/path' },
+ },
+ ],
+ done,
+ );
+ });
+
+ it('discards file changes on all other files', done => {
+ testAction(
+ discardAllChanges,
+ undefined,
+ store.state,
+ [
+ { type: types.DISCARD_FILE_CHANGES, payload: 'discardAll' },
+ { type: types.REMOVE_ALL_CHANGES_FILES },
+ ],
+ [],
+ done,
+ );
+ });
});
describe('closeAllFiles', () => {
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index d464f30b94..cbc2401262 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -1,3 +1,4 @@
+import { resetStore, file } from 'spec/ide/helpers';
import rootActions from '~/ide/stores/actions';
import { createStore } from '~/ide/stores';
import service from '~/ide/services';
@@ -7,7 +8,6 @@ import consts from '~/ide/stores/modules/commit/constants';
import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
import { commitActionTypes } from '~/ide/constants';
-import { resetStore, file } from 'spec/ide/helpers';
import testAction from '../../../../helpers/vuex_action_helper';
const TEST_COMMIT_SHA = '123456789';
diff --git a/spec/javascripts/importer_status_spec.js b/spec/javascripts/importer_status_spec.js
index e7f195ed57..90835e1cc2 100644
--- a/spec/javascripts/importer_status_spec.js
+++ b/spec/javascripts/importer_status_spec.js
@@ -1,6 +1,6 @@
+import MockAdapter from 'axios-mock-adapter';
import { ImporterStatus } from '~/importer_status';
import axios from '~/lib/utils/axios_utils';
-import MockAdapter from 'axios-mock-adapter';
describe('Importer Status', () => {
let instance;
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index 9fce040fd8..4c405fbc4d 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -1,12 +1,12 @@
/* eslint-disable no-unused-vars */
-import GLDropdown from '~/gl_dropdown';
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+import GLDropdown from '~/gl_dropdown';
import axios from '~/lib/utils/axios_utils';
import '~/behaviors/markdown/render_gfm';
import issuableApp from '~/issue_show/components/app.vue';
import eventHub from '~/issue_show/event_hub';
-import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
import issueShowData from '../mock_data';
function formatText(text) {
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
index e10426a985..83e498347f 100644
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ b/spec/javascripts/issue_show/components/description_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
import '~/behaviors/markdown/render_gfm';
-import Description from '~/issue_show/components/description.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import Description from '~/issue_show/components/description.vue';
describe('Description component', () => {
let vm;
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
index 57ab1aa73f..0fcd608010 100644
--- a/spec/javascripts/jobs/components/job_app_spec.js
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -1,11 +1,11 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { waitForMutation } from 'spec/helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
import jobApp from '~/jobs/components/job_app.vue';
import createStore from '~/jobs/store';
import * as types from '~/jobs/store/mutation_types';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import { waitForMutation } from 'spec/helpers/vue_test_utils_helper';
import { resetStore } from '../store/helpers';
import job from '../mock_data';
diff --git a/spec/javascripts/jobs/components/job_container_item_spec.js b/spec/javascripts/jobs/components/job_container_item_spec.js
index 2d108f1ad7..99f6d9a14d 100644
--- a/spec/javascripts/jobs/components/job_container_item_spec.js
+++ b/spec/javascripts/jobs/components/job_container_item_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import JobContainerItem from '~/jobs/components/job_container_item.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import JobContainerItem from '~/jobs/components/job_container_item.vue';
import job from '../mock_data';
describe('JobContainerItem', () => {
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
index 4d782e5bd0..fcaf2b3bb6 100644
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ b/spec/javascripts/jobs/components/job_log_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import component from '~/jobs/components/job_log.vue';
import createStore from '~/jobs/store';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../store/helpers';
describe('Job Log', () => {
diff --git a/spec/javascripts/jobs/components/manual_variables_form_spec.js b/spec/javascripts/jobs/components/manual_variables_form_spec.js
index 093aa90518..1f2bf8674c 100644
--- a/spec/javascripts/jobs/components/manual_variables_form_spec.js
+++ b/spec/javascripts/jobs/components/manual_variables_form_spec.js
@@ -1,9 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import Form from '~/jobs/components/manual_variables_form.vue';
+const localVue = createLocalVue();
+
describe('Manual Variables Form', () => {
let wrapper;
+
const requiredProps = {
action: {
path: '/play',
@@ -14,8 +17,10 @@ describe('Manual Variables Form', () => {
};
const factory = (props = {}) => {
- wrapper = shallowMount(Form, {
+ wrapper = shallowMount(localVue.extend(Form), {
propsData: props,
+ localVue,
+ sync: false,
});
};
@@ -23,8 +28,15 @@ describe('Manual Variables Form', () => {
factory(requiredProps);
});
- afterEach(() => {
- wrapper.destroy();
+ afterEach(done => {
+ // The component has a `nextTick` callback after some events so we need
+ // to wait for those to finish before destroying.
+ setImmediate(() => {
+ wrapper.destroy();
+ wrapper = null;
+
+ done();
+ });
});
it('renders empty form with correct placeholders', () => {
@@ -71,7 +83,7 @@ describe('Manual Variables Form', () => {
});
describe('when deleting a variable', () => {
- it('removes the variable row', () => {
+ beforeEach(done => {
wrapper.vm.variables = [
{
key: 'new key',
@@ -80,6 +92,10 @@ describe('Manual Variables Form', () => {
},
];
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('removes the variable row', () => {
wrapper.find(GlButton).vm.$emit('click');
expect(wrapper.vm.variables.length).toBe(0);
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index a34337310d..e091aece56 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import component from '~/jobs/components/stages_dropdown.vue';
import { trimText } from 'spec/helpers/text_helper';
+import component from '~/jobs/components/stages_dropdown.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Stages Dropdown', () => {
diff --git a/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js b/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
index 48a6b80b36..b67187f1d5 100644
--- a/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
+++ b/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
describe('DelayedJobMixin', () => {
const delayedJobFixture = getJSONFixture('jobs/delayed.json');
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
index 91d1942bdb..c0e8dbf9b2 100644
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ b/spec/javascripts/jobs/store/actions_spec.js
@@ -1,4 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import {
setJobEndpoint,
@@ -27,8 +29,6 @@ import {
} from '~/jobs/store/actions';
import state from '~/jobs/store/state';
import * as types from '~/jobs/store/mutation_types';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
describe('Job State actions', () => {
let mockedState;
diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js
index 5ae5643aef..9d05bdeee2 100644
--- a/spec/javascripts/labels_issue_sidebar_spec.js
+++ b/spec/javascripts/labels_issue_sidebar_spec.js
@@ -2,10 +2,10 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import IssuableContext from '~/issuable_context';
import LabelsSelect from '~/labels_select';
-import _ from 'underscore';
import '~/gl_dropdown';
import 'select2';
diff --git a/spec/javascripts/landing_spec.js b/spec/javascripts/landing_spec.js
index 2fe5a47b63..bffef8fc64 100644
--- a/spec/javascripts/landing_spec.js
+++ b/spec/javascripts/landing_spec.js
@@ -1,5 +1,5 @@
-import Landing from '~/landing';
import Cookies from 'js-cookie';
+import Landing from '~/landing';
describe('Landing', function() {
describe('class constructor', function() {
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 8956bc92e6..e471be608c 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -1,6 +1,6 @@
+import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
-import MockAdapter from 'axios-mock-adapter';
import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data';
import breakpointInstance from '~/breakpoints';
@@ -721,6 +721,28 @@ describe('common_utils', () => {
});
});
+ describe('convertObjectPropsToSnakeCase', () => {
+ it('converts each object key to snake case', () => {
+ const obj = {
+ some: 'some',
+ 'cool object': 'cool object',
+ likeThisLongOne: 'likeThisLongOne',
+ };
+
+ expect(commonUtils.convertObjectPropsToSnakeCase(obj)).toEqual({
+ some: 'some',
+ cool_object: 'cool object',
+ like_this_long_one: 'likeThisLongOne',
+ });
+ });
+
+ it('returns an empty object if there are no keys', () => {
+ ['', {}, [], null].forEach(badObj => {
+ expect(commonUtils.convertObjectPropsToSnakeCase(badObj)).toEqual({});
+ });
+ });
+ });
+
describe('with options', () => {
const objWithoutChildren = {
project_name: 'GitLab CE',
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index f8f835ffde..45b10fc3bd 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,12 +1,11 @@
-/* eslint-disable no-var, no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
+/* eslint-disable no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
import $ from 'jquery';
import LineHighlighter from '~/line_highlighter';
describe('LineHighlighter', function() {
- var clickLine;
preloadFixtures('static/line_highlighter.html');
- clickLine = function(number, eventData = {}) {
+ const clickLine = function(number, eventData = {}) {
if ($.isEmptyObject(eventData)) {
return $(`#L${number}`).click();
} else {
@@ -39,34 +38,30 @@ describe('LineHighlighter', function() {
});
it('highlights a range of lines given in the URL hash', function() {
- var line;
new LineHighlighter({ hash: '#L5-25' });
expect($(`.${this.css}`).length).toBe(21);
- for (line = 5; line <= 25; line += 1) {
+ 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() {
- var spy;
- spy = spyOn($, 'scrollTo');
+ const spy = spyOn($, 'scrollTo');
new LineHighlighter({ hash: '#L5-25' });
expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
});
it('discards click events', function() {
- var spy;
- spy = spyOnEvent('a[data-line-number]', 'click');
+ const spy = spyOnEvent('a[data-line-number]', 'click');
clickLine(13);
expect(spy).toHaveBeenPrevented();
});
it('handles garbage input from the hash', function() {
- var func;
- func = function() {
+ const func = function() {
return new LineHighlighter({ fileHolderSelector: '#blob-content-holder' });
};
@@ -76,8 +71,7 @@ describe('LineHighlighter', function() {
describe('clickHandler', function() {
it('handles clicking on a child icon element', function() {
- var spy;
- spy = spyOn(this['class'], 'setHash').and.callThrough();
+ const spy = spyOn(this['class'], 'setHash').and.callThrough();
$('#L13 i')
.mousedown()
.click();
@@ -102,8 +96,7 @@ describe('LineHighlighter', function() {
});
it('sets the hash', function() {
- var spy;
- spy = spyOn(this['class'], 'setHash').and.callThrough();
+ const spy = spyOn(this['class'], 'setHash').and.callThrough();
clickLine(13);
expect(spy).toHaveBeenCalledWith(13);
@@ -112,8 +105,7 @@ describe('LineHighlighter', function() {
describe('with shiftKey', function() {
it('sets the hash', function() {
- var spy;
- spy = spyOn(this['class'], 'setHash').and.callThrough();
+ const spy = spyOn(this['class'], 'setHash').and.callThrough();
clickLine(13);
clickLine(20, {
shiftKey: true,
@@ -134,8 +126,7 @@ describe('LineHighlighter', function() {
});
it('sets the hash', function() {
- var spy;
- spy = spyOn(this['class'], 'setHash');
+ const spy = spyOn(this['class'], 'setHash');
clickLine(13, {
shiftKey: true,
});
@@ -146,27 +137,25 @@ describe('LineHighlighter', function() {
describe('with existing single-line highlight', function() {
it('uses existing line as last line when target is lesser', function() {
- var line;
clickLine(20);
clickLine(15, {
shiftKey: true,
});
expect($(`.${this.css}`).length).toBe(6);
- for (line = 15; line <= 20; line += 1) {
+ 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() {
- var line;
clickLine(5);
clickLine(10, {
shiftKey: true,
});
expect($(`.${this.css}`).length).toBe(6);
- for (line = 5; line <= 10; line += 1) {
+ for (let line = 5; line <= 10; line += 1) {
expect($(`#LC${line}`)).toHaveClass(this.css);
}
});
@@ -183,25 +172,23 @@ describe('LineHighlighter', function() {
});
it('uses target as first line when it is less than existing first line', function() {
- var line;
clickLine(5, {
shiftKey: true,
});
expect($(`.${this.css}`).length).toBe(6);
- for (line = 5; line <= 10; line += 1) {
+ 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() {
- var line;
clickLine(15, {
shiftKey: true,
});
expect($(`.${this.css}`).length).toBe(6);
- for (line = 10; line <= 15; line += 1) {
+ for (let line = 10; line <= 15; line += 1) {
expect($(`#LC${line}`)).toHaveClass(this.css);
}
});
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 54071ccc5c..dc61482fdf 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -89,6 +89,7 @@ describe('MergeRequest', function() {
});
});
+ // 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
diff --git a/spec/javascripts/monitoring/components/dashboard_spec.js b/spec/javascripts/monitoring/components/dashboard_spec.js
index 0f20171726..b29bac2182 100644
--- a/spec/javascripts/monitoring/components/dashboard_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_spec.js
@@ -4,11 +4,14 @@ import { GlToast } from '@gitlab/ui';
import VueDraggable from 'vuedraggable';
import MockAdapter from 'axios-mock-adapter';
import Dashboard from '~/monitoring/components/dashboard.vue';
+import { metricStates } from '~/monitoring/constants';
+import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
import * as types from '~/monitoring/stores/mutation_types';
import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils';
import {
metricsGroupsAPIResponse,
+ mockedEmptyResult,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
mockApiEndpoint,
@@ -29,6 +32,7 @@ const propsData = {
emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
emptyLoadingSvgPath: '/path/to/loading.svg',
emptyNoDataSvgPath: '/path/to/no-data.svg',
+ emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
currentEnvironmentName: 'production',
@@ -43,24 +47,31 @@ const resetSpy = spy => {
}
};
-export default propsData;
+let expectedPanelCount;
function setupComponentStore(component) {
+ // Load 2 panel groups
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
);
- // Load 2 panels to the dashboard
+ // Load 3 panels to the dashboard, one with an empty result
component.$store.commit(
- `monitoringDashboard/${types.SET_QUERY_RESULT}`,
+ `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
+ mockedEmptyResult,
+ );
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
mockedQueryResultPayload,
);
component.$store.commit(
- `monitoringDashboard/${types.SET_QUERY_RESULT}`,
+ `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
mockedQueryResultPayloadCoresTotal,
);
+ expectedPanelCount = 2;
+
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
@@ -72,6 +83,17 @@ describe('Dashboard', () => {
let mock;
let store;
let component;
+ let wrapper;
+
+ const createComponentWrapper = (props = {}, options = {}) => {
+ wrapper = shallowMount(localVue.extend(DashboardComponent), {
+ localVue,
+ sync: false,
+ propsData: { ...propsData, ...props },
+ store,
+ ...options,
+ });
+ };
beforeEach(() => {
setFixtures(`
@@ -81,13 +103,16 @@ describe('Dashboard', () => {
store = createStore();
mock = new MockAdapter(axios);
- DashboardComponent = Vue.extend(Dashboard);
+ DashboardComponent = localVue.extend(Dashboard);
});
afterEach(() => {
if (component) {
component.$destroy();
}
+ if (wrapper) {
+ wrapper.destroy();
+ }
mock.restore();
});
@@ -112,26 +137,15 @@ describe('Dashboard', () => {
describe('no data found', () => {
it('shows the environment selector dropdown', () => {
- component = new DashboardComponent({
- el: document.querySelector('.prometheus-graphs'),
- propsData: { ...propsData, showEmptyState: true },
- store,
- });
+ createComponentWrapper();
- expect(component.$el.querySelector('.js-environments-dropdown')).toBeTruthy();
+ expect(wrapper.find('.js-environments-dropdown').exists()).toBeTruthy();
});
});
describe('cluster health', () => {
- let wrapper;
-
beforeEach(done => {
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- propsData: { ...propsData, hasMetrics: true },
- store,
- });
+ createComponentWrapper({ hasMetrics: true });
// all_dashboards is not defined in health dashboards
wrapper.vm.$store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined);
@@ -259,7 +273,7 @@ describe('Dashboard', () => {
metricsGroupsAPIResponse,
);
component.$store.commit(
- `monitoringDashboard/${types.SET_QUERY_RESULT}`,
+ `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
mockedQueryResultPayload,
);
@@ -382,10 +396,36 @@ describe('Dashboard', () => {
});
});
- describe('drag and drop function', () => {
- let wrapper;
- let expectedPanelCount; // also called metrics, naming to be improved: https://gitlab.com/gitlab-org/gitlab/issues/31565
+ describe('when one of the metrics is missing', () => {
+ beforeEach(() => {
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
+ });
+ beforeEach(done => {
+ createComponentWrapper({ hasMetrics: true });
+ setupComponentStore(wrapper.vm);
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('shows a group empty area', () => {
+ const emptyGroup = wrapper.findAll({ ref: 'empty-group' });
+
+ expect(emptyGroup).toHaveLength(1);
+ expect(emptyGroup.is(GroupEmptyState)).toBe(true);
+ });
+
+ it('group empty area displays a NO_DATA state', () => {
+ expect(
+ wrapper
+ .findAll({ ref: 'empty-group' })
+ .at(0)
+ .props('selectedState'),
+ ).toEqual(metricStates.NO_DATA);
+ });
+ });
+
+ describe('drag and drop function', () => {
const findDraggables = () => wrapper.findAll(VueDraggable);
const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
@@ -393,20 +433,10 @@ describe('Dashboard', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
- expectedPanelCount = metricsGroupsAPIResponse.reduce(
- (acc, group) => group.panels.length + acc,
- 0,
- );
});
beforeEach(done => {
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- propsData: { ...propsData, hasMetrics: true },
- store,
- attachToDocument: true,
- });
+ createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
setupComponentStore(wrapper.vm);
@@ -455,22 +485,20 @@ describe('Dashboard', () => {
it('metrics can be swapped', done => {
const firstDraggable = findDraggables().at(0);
- const mockMetrics = [...metricsGroupsAPIResponse[0].panels];
- const value = () => firstDraggable.props('value');
+ const mockMetrics = [...metricsGroupsAPIResponse[1].panels];
- expect(value().length).toBe(mockMetrics.length);
- value().forEach((metric, i) => {
- expect(metric.title).toBe(mockMetrics[i].title);
- });
+ const firstTitle = mockMetrics[0].title;
+ const secondTitle = mockMetrics[1].title;
// swap two elements and `input` them
[mockMetrics[0], mockMetrics[1]] = [mockMetrics[1], mockMetrics[0]];
firstDraggable.vm.$emit('input', mockMetrics);
- firstDraggable.vm.$nextTick(() => {
- value().forEach((metric, i) => {
- expect(metric.title).toBe(mockMetrics[i].title);
- });
+ wrapper.vm.$nextTick(() => {
+ const { panels } = wrapper.vm.dashboard.panel_groups[1];
+
+ expect(panels[1].title).toEqual(firstTitle);
+ expect(panels[0].title).toEqual(secondTitle);
done();
});
});
@@ -502,7 +530,6 @@ describe('Dashboard', () => {
// https://gitlab.com/gitlab-org/gitlab-ce/issues/66922
// eslint-disable-next-line jasmine/no-disabled-tests
xdescribe('link to chart', () => {
- let wrapper;
const currentDashboard = 'TEST_DASHBOARD';
localVue.use(GlToast);
const link = () => wrapper.find('.js-chart-link');
@@ -511,13 +538,7 @@ describe('Dashboard', () => {
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- attachToDocument: true,
- propsData: { ...propsData, hasMetrics: true, currentDashboard },
- store,
- });
+ createComponentWrapper({ hasMetrics: true, currentDashboard }, { attachToDocument: true });
setTimeout(done);
});
@@ -587,7 +608,7 @@ describe('Dashboard', () => {
setupComponentStore(component);
return Vue.nextTick().then(() => {
- promPanel = component.$el.querySelector('.prometheus-panel');
+ [, promPanel] = component.$el.querySelectorAll('.prometheus-panel');
promGroup = promPanel.querySelector('.prometheus-graph-group');
panelToggle = promPanel.querySelector('.js-graph-group-toggle');
chart = promGroup.querySelector('.position-relative svg');
@@ -614,19 +635,12 @@ describe('Dashboard', () => {
});
describe('dashboard edit link', () => {
- let wrapper;
const findEditLink = () => wrapper.find('.js-edit-link');
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- attachToDocument: true,
- propsData: { ...propsData, hasMetrics: true },
- store,
- });
+ createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
wrapper.vm.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
diff --git a/spec/javascripts/monitoring/components/graph_group_spec.js b/spec/javascripts/monitoring/components/graph_group_spec.js
index 068c4b5302..43ca17c3cb 100644
--- a/spec/javascripts/monitoring/components/graph_group_spec.js
+++ b/spec/javascripts/monitoring/components/graph_group_spec.js
@@ -1,47 +1,120 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import GraphGroup from '~/monitoring/components/graph_group.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+const localVue = createLocalVue();
describe('Graph group component', () => {
- let graphGroup;
+ let wrapper;
+
+ const findGroup = () => wrapper.find({ ref: 'graph-group' });
+ const findContent = () => wrapper.find({ ref: 'graph-group-content' });
+ const findCaretIcon = () => wrapper.find(Icon);
+
+ const createComponent = propsData => {
+ wrapper = shallowMount(localVue.extend(GraphGroup), {
+ propsData,
+ sync: false,
+ localVue,
+ });
+ };
afterEach(() => {
- graphGroup.destroy();
+ wrapper.destroy();
});
- describe('When groups can be collapsed', () => {
+ describe('When group is not collapsed', () => {
beforeEach(() => {
- graphGroup = shallowMount(GraphGroup, {
- propsData: {
- name: 'panel',
- collapseGroup: true,
- },
+ createComponent({
+ name: 'panel',
+ collapseGroup: false,
});
});
- it('should show the angle-down caret icon when collapseGroup is true', () => {
- expect(graphGroup.vm.caretIcon).toBe('angle-down');
+ it('should show the angle-down caret icon', () => {
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().props('name')).toBe('angle-down');
});
- it('should show the angle-right caret icon when collapseGroup is false', () => {
- graphGroup.vm.collapse();
+ it('should show the angle-right caret icon when the user collapses the group', done => {
+ wrapper.vm.collapse();
- expect(graphGroup.vm.caretIcon).toBe('angle-right');
+ wrapper.vm.$nextTick(() => {
+ expect(findContent().isVisible()).toBe(false);
+ expect(findCaretIcon().props('name')).toBe('angle-right');
+ done();
+ });
});
- });
- describe('When groups can not be collapsed', () => {
- beforeEach(() => {
- graphGroup = shallowMount(GraphGroup, {
- propsData: {
+ it('should show the open the group when collapseGroup is set to true', done => {
+ wrapper.setProps({
+ collapseGroup: true,
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().props('name')).toBe('angle-down');
+ done();
+ });
+ });
+
+ describe('When group is collapsed', () => {
+ beforeEach(() => {
+ createComponent({
name: 'panel',
collapseGroup: true,
+ });
+ });
+
+ it('should show the angle-down caret icon when collapseGroup is true', () => {
+ expect(wrapper.vm.caretIcon).toBe('angle-right');
+ });
+
+ it('should show the angle-right caret icon when collapseGroup is false', () => {
+ wrapper.vm.collapse();
+
+ expect(wrapper.vm.caretIcon).toBe('angle-down');
+ });
+ });
+
+ describe('When groups can not be collapsed', () => {
+ beforeEach(() => {
+ createComponent({
+ name: 'panel',
showPanels: false,
- },
+ collapseGroup: false,
+ });
+ });
+
+ it('should not have a container when showPanels is false', () => {
+ expect(findGroup().exists()).toBe(false);
+ expect(findContent().exists()).toBe(true);
});
});
- it('should not contain a prometheus-graph-group container when showPanels is false', () => {
- expect(graphGroup.vm.$el.querySelector('.prometheus-graph-group')).toBe(null);
+ describe('When group does not show a panel heading', () => {
+ beforeEach(() => {
+ createComponent({
+ name: 'panel',
+ showPanels: false,
+ collapseGroup: false,
+ });
+ });
+
+ it('should collapse the panel content', () => {
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().exists()).toBe(false);
+ });
+
+ it('should show the panel content when clicked', done => {
+ wrapper.vm.collapse();
+
+ wrapper.vm.$nextTick(() => {
+ expect(findContent().isVisible()).toBe(true);
+ expect(findCaretIcon().exists()).toBe(false);
+ done();
+ });
+ });
});
});
});
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index f9cc839bde..c80401e8c1 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -1,250 +1,5 @@
-import {
- anomalyMockGraphData as importedAnomalyMockGraphData,
- metricsGroupsAPIResponse as importedMetricsGroupsAPIResponse,
- environmentData as importedEnvironmentData,
- dashboardGitResponse as importedDashboardGitResponse,
-} from '../../frontend/monitoring/mock_data';
+// No new code should be added to this file. Instead, modify the
+// file this one re-exports from. For more detail about why, see:
+// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-export const anomalyMockGraphData = importedAnomalyMockGraphData;
-export const metricsGroupsAPIResponse = importedMetricsGroupsAPIResponse;
-export const environmentData = importedEnvironmentData;
-export const dashboardGitResponse = importedDashboardGitResponse;
-
-export const mockApiEndpoint = `${gl.TEST_HOST}/monitoring/mock`;
-
-export const mockedQueryResultPayload = {
- metricId: '17_system_metrics_kubernetes_container_memory_average',
- result: [
- {
- metric: {},
- values: [
- [1563272065.589, '10.396484375'],
- [1563272125.589, '10.333984375'],
- [1563272185.589, '10.333984375'],
- [1563272245.589, '10.333984375'],
- [1563272305.589, '10.333984375'],
- [1563272365.589, '10.333984375'],
- [1563272425.589, '10.38671875'],
- [1563272485.589, '10.333984375'],
- [1563272545.589, '10.333984375'],
- [1563272605.589, '10.333984375'],
- [1563272665.589, '10.333984375'],
- [1563272725.589, '10.333984375'],
- [1563272785.589, '10.396484375'],
- [1563272845.589, '10.333984375'],
- [1563272905.589, '10.333984375'],
- [1563272965.589, '10.3984375'],
- [1563273025.589, '10.337890625'],
- [1563273085.589, '10.34765625'],
- [1563273145.589, '10.337890625'],
- [1563273205.589, '10.337890625'],
- [1563273265.589, '10.337890625'],
- [1563273325.589, '10.337890625'],
- [1563273385.589, '10.337890625'],
- [1563273445.589, '10.337890625'],
- [1563273505.589, '10.337890625'],
- [1563273565.589, '10.337890625'],
- [1563273625.589, '10.337890625'],
- [1563273685.589, '10.337890625'],
- [1563273745.589, '10.337890625'],
- [1563273805.589, '10.337890625'],
- [1563273865.589, '10.390625'],
- [1563273925.589, '10.390625'],
- ],
- },
- ],
-};
-
-export const mockedQueryResultPayloadCoresTotal = {
- metricId: '13_system_metrics_kubernetes_container_cores_total',
- result: [
- {
- metric: {},
- values: [
- [1563272065.589, '9.396484375'],
- [1563272125.589, '9.333984375'],
- [1563272185.589, '9.333984375'],
- [1563272245.589, '9.333984375'],
- [1563272305.589, '9.333984375'],
- [1563272365.589, '9.333984375'],
- [1563272425.589, '9.38671875'],
- [1563272485.589, '9.333984375'],
- [1563272545.589, '9.333984375'],
- [1563272605.589, '9.333984375'],
- [1563272665.589, '9.333984375'],
- [1563272725.589, '9.333984375'],
- [1563272785.589, '9.396484375'],
- [1563272845.589, '9.333984375'],
- [1563272905.589, '9.333984375'],
- [1563272965.589, '9.3984375'],
- [1563273025.589, '9.337890625'],
- [1563273085.589, '9.34765625'],
- [1563273145.589, '9.337890625'],
- [1563273205.589, '9.337890625'],
- [1563273265.589, '9.337890625'],
- [1563273325.589, '9.337890625'],
- [1563273385.589, '9.337890625'],
- [1563273445.589, '9.337890625'],
- [1563273505.589, '9.337890625'],
- [1563273565.589, '9.337890625'],
- [1563273625.589, '9.337890625'],
- [1563273685.589, '9.337890625'],
- [1563273745.589, '9.337890625'],
- [1563273805.589, '9.337890625'],
- [1563273865.589, '9.390625'],
- [1563273925.589, '9.390625'],
- ],
- },
- ],
-};
-
-export const graphDataPrometheusQuery = {
- title: 'Super Chart A2',
- type: 'single-stat',
- weight: 2,
- metrics: [
- {
- id: 'metric_a1',
- metric_id: 2,
- query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024',
- unit: 'MB',
- label: 'Total Consumption',
- prometheus_endpoint_path:
- '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
- },
- ],
- queries: [
- {
- metricId: null,
- id: 'metric_a1',
- metric_id: 2,
- query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024',
- unit: 'MB',
- label: 'Total Consumption',
- prometheus_endpoint_path:
- '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
- result: [
- {
- metric: { job: 'prometheus' },
- value: ['2019-06-26T21:03:20.881Z', 91],
- },
- ],
- },
- ],
-};
-
-export const graphDataPrometheusQueryRange = {
- title: 'Super Chart A1',
- type: 'area-chart',
- weight: 2,
- metrics: [
- {
- id: 'metric_a1',
- metric_id: 2,
- query_range:
- 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
- unit: 'MB',
- label: 'Total Consumption',
- prometheus_endpoint_path:
- '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
- },
- ],
- queries: [
- {
- metricId: '10',
- id: 'metric_a1',
- metric_id: 2,
- query_range:
- 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
- unit: 'MB',
- label: 'Total Consumption',
- prometheus_endpoint_path:
- '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
- result: [
- {
- metric: {},
- values: [[1495700554.925, '8.0390625'], [1495700614.925, '8.0390625']],
- },
- ],
- },
- ],
-};
-
-export const graphDataPrometheusQueryRangeMultiTrack = {
- title: 'Super Chart A3',
- type: 'heatmap',
- weight: 3,
- x_label: 'Status Code',
- y_label: 'Time',
- metrics: [],
- queries: [
- {
- metricId: '1',
- id: 'response_metrics_nginx_ingress_throughput_status_code',
- query_range:
- 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[60m])) by (status_code)',
- unit: 'req / sec',
- label: 'Status Code',
- metric_id: 1,
- prometheus_endpoint_path:
- '/root/rails_nodb/environments/3/prometheus/api/v1/query_range?query=sum%28rate%28nginx_upstream_responses_total%7Bupstream%3D~%22%25%7Bkube_namespace%7D-%25%7Bci_environment_slug%7D-.%2A%22%7D%5B2m%5D%29%29+by+%28status_code%29',
- result: [
- {
- metric: { status_code: '1xx' },
- values: [
- ['2019-08-30T15:00:00.000Z', 0],
- ['2019-08-30T16:00:00.000Z', 2],
- ['2019-08-30T17:00:00.000Z', 0],
- ['2019-08-30T18:00:00.000Z', 0],
- ['2019-08-30T19:00:00.000Z', 0],
- ['2019-08-30T20:00:00.000Z', 3],
- ],
- },
- {
- metric: { status_code: '2xx' },
- values: [
- ['2019-08-30T15:00:00.000Z', 1],
- ['2019-08-30T16:00:00.000Z', 3],
- ['2019-08-30T17:00:00.000Z', 6],
- ['2019-08-30T18:00:00.000Z', 10],
- ['2019-08-30T19:00:00.000Z', 8],
- ['2019-08-30T20:00:00.000Z', 6],
- ],
- },
- {
- metric: { status_code: '3xx' },
- values: [
- ['2019-08-30T15:00:00.000Z', 1],
- ['2019-08-30T16:00:00.000Z', 2],
- ['2019-08-30T17:00:00.000Z', 3],
- ['2019-08-30T18:00:00.000Z', 3],
- ['2019-08-30T19:00:00.000Z', 2],
- ['2019-08-30T20:00:00.000Z', 1],
- ],
- },
- {
- metric: { status_code: '4xx' },
- values: [
- ['2019-08-30T15:00:00.000Z', 2],
- ['2019-08-30T16:00:00.000Z', 0],
- ['2019-08-30T17:00:00.000Z', 0],
- ['2019-08-30T18:00:00.000Z', 2],
- ['2019-08-30T19:00:00.000Z', 0],
- ['2019-08-30T20:00:00.000Z', 2],
- ],
- },
- {
- metric: { status_code: '5xx' },
- values: [
- ['2019-08-30T15:00:00.000Z', 0],
- ['2019-08-30T16:00:00.000Z', 1],
- ['2019-08-30T17:00:00.000Z', 0],
- ['2019-08-30T18:00:00.000Z', 0],
- ['2019-08-30T19:00:00.000Z', 0],
- ['2019-08-30T20:00:00.000Z', 2],
- ],
- },
- ],
- },
- ],
-};
+export * from '../../frontend/monitoring/mock_data';
diff --git a/spec/javascripts/monitoring/utils_spec.js b/spec/javascripts/monitoring/utils_spec.js
deleted file mode 100644
index 202b4ec8f2..0000000000
--- a/spec/javascripts/monitoring/utils_spec.js
+++ /dev/null
@@ -1,345 +0,0 @@
-import {
- getTimeDiff,
- getTimeWindow,
- graphDataValidatorForValues,
- isDateTimePickerInputValid,
- truncateZerosInDateTime,
- stringToISODate,
- ISODateToString,
- isValidDate,
- graphDataValidatorForAnomalyValues,
-} from '~/monitoring/utils';
-import { timeWindows, timeWindowsKeyNames } from '~/monitoring/constants';
-import {
- graphDataPrometheusQuery,
- graphDataPrometheusQueryRange,
- anomalyMockGraphData,
-} from './mock_data';
-
-describe('getTimeDiff', () => {
- function secondsBetween({ start, end }) {
- return (new Date(end) - new Date(start)) / 1000;
- }
-
- function minutesBetween(timeRange) {
- return secondsBetween(timeRange) / 60;
- }
-
- function hoursBetween(timeRange) {
- return minutesBetween(timeRange) / 60;
- }
-
- it('defaults to an 8 hour (28800s) difference', () => {
- const params = getTimeDiff();
-
- expect(hoursBetween(params)).toEqual(8);
- });
-
- it('accepts time window as an argument', () => {
- const params = getTimeDiff('thirtyMinutes');
-
- expect(minutesBetween(params)).toEqual(30);
- });
-
- it('returns a value for every defined time window', () => {
- const nonDefaultWindows = Object.keys(timeWindows).filter(window => window !== 'eightHours');
-
- nonDefaultWindows.forEach(timeWindow => {
- const params = getTimeDiff(timeWindow);
-
- // Ensure we're not returning the default
- expect(hoursBetween(params)).not.toEqual(8);
- });
- });
-});
-
-describe('getTimeWindow', () => {
- [
- {
- args: [
- {
- start: '2019-10-01T18:27:47.000Z',
- end: '2019-10-01T21:27:47.000Z',
- },
- ],
- expected: timeWindowsKeyNames.threeHours,
- },
- {
- args: [
- {
- start: '2019-10-01T28:27:47.000Z',
- end: '2019-10-01T21:27:47.000Z',
- },
- ],
- expected: null,
- },
- {
- args: [
- {
- start: '',
- end: '',
- },
- ],
- expected: null,
- },
- {
- args: [
- {
- start: null,
- end: null,
- },
- ],
- expected: null,
- },
- {
- args: [{}],
- expected: null,
- },
- ].forEach(({ args, expected }) => {
- it(`returns "${expected}" with args=${JSON.stringify(args)}`, () => {
- expect(getTimeWindow(...args)).toEqual(expected);
- });
- });
-});
-
-describe('graphDataValidatorForValues', () => {
- /*
- * When dealing with a metric using the query format, e.g.
- * query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024'
- * the validator will look for the `value` key instead of `values`
- */
- it('validates data with the query format', () => {
- const validGraphData = graphDataValidatorForValues(true, graphDataPrometheusQuery);
-
- expect(validGraphData).toBe(true);
- });
-
- /*
- * When dealing with a metric using the query?range format, e.g.
- * query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
- * the validator will look for the `values` key instead of `value`
- */
- it('validates data with the query_range format', () => {
- const validGraphData = graphDataValidatorForValues(false, graphDataPrometheusQueryRange);
-
- expect(validGraphData).toBe(true);
- });
-});
-
-describe('stringToISODate', () => {
- ['', 'null', undefined, 'abc'].forEach(input => {
- it(`throws error for invalid input like ${input}`, done => {
- try {
- stringToISODate(input);
- } catch (e) {
- expect(e).toBeDefined();
- done();
- }
- });
- });
- [
- {
- input: '2019-09-09 01:01:01',
- output: '2019-09-09T01:01:01Z',
- },
- {
- input: '2019-09-09 00:00:00',
- output: '2019-09-09T00:00:00Z',
- },
- {
- input: '2019-09-09 23:59:59',
- output: '2019-09-09T23:59:59Z',
- },
- {
- input: '2019-09-09',
- output: '2019-09-09T00:00:00Z',
- },
- ].forEach(({ input, output }) => {
- it(`returns ${output} from ${input}`, () => {
- expect(stringToISODate(input)).toBe(output);
- });
- });
-});
-
-describe('ISODateToString', () => {
- [
- {
- input: new Date('2019-09-09T00:00:00.000Z'),
- output: '2019-09-09 00:00:00',
- },
- {
- input: new Date('2019-09-09T07:00:00.000Z'),
- output: '2019-09-09 07:00:00',
- },
- ].forEach(({ input, output }) => {
- it(`ISODateToString return ${output} for ${input}`, () => {
- expect(ISODateToString(input)).toBe(output);
- });
- });
-});
-
-describe('truncateZerosInDateTime', () => {
- [
- {
- input: '',
- output: '',
- },
- {
- input: '2019-10-10',
- output: '2019-10-10',
- },
- {
- input: '2019-10-10 00:00:01',
- output: '2019-10-10 00:00:01',
- },
- {
- input: '2019-10-10 00:00:00',
- output: '2019-10-10',
- },
- ].forEach(({ input, output }) => {
- it(`truncateZerosInDateTime return ${output} for ${input}`, () => {
- expect(truncateZerosInDateTime(input)).toBe(output);
- });
- });
-});
-
-describe('isValidDate', () => {
- [
- {
- input: '2019-09-09T00:00:00.000Z',
- output: true,
- },
- {
- input: '2019-09-09T000:00.000Z',
- output: false,
- },
- {
- input: 'a2019-09-09T000:00.000Z',
- output: false,
- },
- {
- input: '2019-09-09T',
- output: false,
- },
- {
- input: '2019-09-09',
- output: true,
- },
- {
- input: '2019-9-9',
- output: true,
- },
- {
- input: '2019-9-',
- output: true,
- },
- {
- input: '2019--',
- output: false,
- },
- {
- input: '2019',
- output: true,
- },
- {
- input: '',
- output: false,
- },
- {
- input: null,
- output: false,
- },
- ].forEach(({ input, output }) => {
- it(`isValidDate return ${output} for ${input}`, () => {
- expect(isValidDate(input)).toBe(output);
- });
- });
-});
-
-describe('isDateTimePickerInputValid', () => {
- [
- {
- input: null,
- output: false,
- },
- {
- input: '',
- output: false,
- },
- {
- input: 'xxxx-xx-xx',
- output: false,
- },
- {
- input: '9999-99-19',
- output: false,
- },
- {
- input: '2019-19-23',
- output: false,
- },
- {
- input: '2019-09-23',
- output: true,
- },
- {
- input: '2019-09-23 x',
- output: false,
- },
- {
- input: '2019-09-29 0:0:0',
- output: false,
- },
- {
- input: '2019-09-29 00:00:00',
- output: true,
- },
- {
- input: '2019-09-29 24:24:24',
- output: false,
- },
- {
- input: '2019-09-29 23:24:24',
- output: true,
- },
- {
- input: '2019-09-29 23:24:24 ',
- output: false,
- },
- ].forEach(({ input, output }) => {
- it(`returns ${output} for ${input}`, () => {
- expect(isDateTimePickerInputValid(input)).toBe(output);
- });
- });
-});
-
-describe('graphDataValidatorForAnomalyValues', () => {
- let oneQuery;
- let threeQueries;
- let fourQueries;
- beforeEach(() => {
- oneQuery = graphDataPrometheusQuery;
- threeQueries = anomalyMockGraphData;
-
- const queries = [...threeQueries.queries];
- queries.push(threeQueries.queries[0]);
- fourQueries = {
- ...anomalyMockGraphData,
- queries,
- };
- });
- /*
- * Anomaly charts can accept results for exactly 3 queries,
- */
- it('validates passes with the right query format', () => {
- expect(graphDataValidatorForAnomalyValues(threeQueries)).toBe(true);
- });
-
- it('validation fails for wrong format, 1 metric', () => {
- expect(graphDataValidatorForAnomalyValues(oneQuery)).toBe(false);
- });
-
- it('validation fails for wrong format, more than 3 metrics', () => {
- expect(graphDataValidatorForAnomalyValues(fourQueries)).toBe(false);
- });
-});
diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/javascripts/notebook/cells/markdown_spec.js
index 540fc8a21f..07b18d97cd 100644
--- a/spec/javascripts/notebook/cells/markdown_spec.js
+++ b/spec/javascripts/notebook/cells/markdown_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import MarkdownComponent from '~/notebook/cells/markdown.vue';
import katex from 'katex';
+import MarkdownComponent from '~/notebook/cells/markdown.vue';
const Component = Vue.extend(MarkdownComponent);
@@ -49,7 +49,7 @@ describe('Markdown component', () => {
});
Vue.nextTick(() => {
- expect(vm.$el.querySelector('a')).toBeNull();
+ expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
done();
});
diff --git a/spec/javascripts/notes/components/diff_with_note_spec.js b/spec/javascripts/notes/components/diff_with_note_spec.js
index f849fe9d8b..573aac2c3e 100644
--- a/spec/javascripts/notes/components/diff_with_note_spec.js
+++ b/spec/javascripts/notes/components/diff_with_note_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { mountComponentWithStore } from 'spec/helpers';
import DiffWithNote from '~/notes/components/diff_with_note.vue';
import { createStore } from '~/mr_notes/stores';
-import { mountComponentWithStore } from 'spec/helpers';
const discussionFixture = 'merge_requests/diff_discussion.json';
const imageDiscussionFixture = 'merge_requests/image_diff_discussion.json';
diff --git a/spec/javascripts/notes/components/discussion_counter_spec.js b/spec/javascripts/notes/components/discussion_counter_spec.js
index fecc0d604b..de1fd87517 100644
--- a/spec/javascripts/notes/components/discussion_counter_spec.js
+++ b/spec/javascripts/notes/components/discussion_counter_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import createStore from '~/notes/stores';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
describe('DiscussionCounter component', () => {
@@ -27,6 +27,8 @@ describe('DiscussionCounter component', () => {
describe('methods', () => {
describe('jumpToFirstUnresolvedDiscussion', () => {
it('expands unresolved discussion', () => {
+ window.mrTabs.currentAction = 'show';
+
spyOn(vm, 'expandDiscussion').and.stub();
const discussions = [
{
@@ -47,14 +49,39 @@ describe('DiscussionCounter component', () => {
...store.state,
discussions,
});
- setFixtures(`
-
- `);
-
vm.jumpToFirstUnresolvedDiscussion();
expect(vm.expandDiscussion).toHaveBeenCalledWith({ discussionId: firstDiscussionId });
});
+
+ it('jumps to first unresolved discussion from diff tab if all diff discussions are resolved', () => {
+ window.mrTabs.currentAction = 'diff';
+ spyOn(vm, 'switchToDiscussionsTabAndJumpTo').and.stub();
+
+ const unresolvedId = discussionMock.id + 1;
+ const discussions = [
+ {
+ ...discussionMock,
+ id: discussionMock.id,
+ diff_discussion: true,
+ notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }],
+ resolved: true,
+ },
+ {
+ ...discussionMock,
+ id: unresolvedId,
+ notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: false }],
+ resolved: false,
+ },
+ ];
+ store.replaceState({
+ ...store.state,
+ discussions,
+ });
+ vm.jumpToFirstUnresolvedDiscussion();
+
+ expect(vm.switchToDiscussionsTabAndJumpTo).toHaveBeenCalledWith(unresolvedId);
+ });
});
});
});
diff --git a/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js b/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js
index b2a91c9919..3be1f0be0d 100644
--- a/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js
+++ b/spec/javascripts/notes/components/discussion_resolve_with_issue_button_spec.js
@@ -1,7 +1,7 @@
import { GlButton } from '@gitlab/ui';
-import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
+import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
const localVue = createLocalVue();
diff --git a/spec/javascripts/notes/components/note_actions/reply_button_spec.js b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
index 003773d07e..aa39ab1583 100644
--- a/spec/javascripts/notes/components/note_actions/reply_button_spec.js
+++ b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
@@ -2,15 +2,14 @@ import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import ReplyButton from '~/notes/components/note_actions/reply_button.vue';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('ReplyButton', () => {
let wrapper;
beforeEach(() => {
- const localVue = createLocalVue();
-
- localVue.use(Vuex);
-
- wrapper = mount(ReplyButton, {
+ wrapper = mount(localVue.extend(ReplyButton), {
sync: false,
localVue,
});
diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js
index 1f2c07385a..2e0694869b 100644
--- a/spec/javascripts/notes/components/note_actions_spec.js
+++ b/spec/javascripts/notes/components/note_actions_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import { shallowMount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { TEST_HOST } from 'spec/test_constants';
import createStore from '~/notes/stores';
import noteActions from '~/notes/components/note_actions.vue';
-import { TEST_HOST } from 'spec/test_constants';
import { userDataMock } from '../mock_data';
describe('noteActions', () => {
@@ -12,7 +12,7 @@ describe('noteActions', () => {
const shallowMountNoteActions = propsData => {
const localVue = createLocalVue();
- return shallowMount(noteActions, {
+ return shallowMount(localVue.extend(noteActions), {
store,
propsData,
localVue,
diff --git a/spec/javascripts/notes/components/note_awards_list_spec.js b/spec/javascripts/notes/components/note_awards_list_spec.js
index ede541a524..90aa168427 100644
--- a/spec/javascripts/notes/components/note_awards_list_spec.js
+++ b/spec/javascripts/notes/components/note_awards_list_spec.js
@@ -61,6 +61,66 @@ describe('note_awards_list component', () => {
expect(vm.$el.querySelector('.js-add-award')).toBeDefined();
});
+ describe('when the user name contains special HTML characters', () => {
+ const createAwardEmoji = (_, index) => ({
+ name: 'art',
+ user: { id: index, name: `&<>"\`'-${index}`, username: `user-${index}` },
+ });
+
+ const mountComponent = () => {
+ const Component = Vue.extend(awardsNote);
+ vm = new Component({
+ store,
+ propsData: {
+ awards: awardsMock,
+ noteAuthorId: 0,
+ noteId: '545',
+ canAwardEmoji: true,
+ toggleAwardPath: '/gitlab-org/gitlab-foss/notes/545/toggle_award_emoji',
+ },
+ }).$mount();
+ };
+
+ const findTooltip = () =>
+ vm.$el.querySelector('[data-original-title]').getAttribute('data-original-title');
+
+ it('should only escape & and " characters', () => {
+ awardsMock = [...new Array(1)].map(createAwardEmoji);
+ mountComponent();
+ const escapedName = awardsMock[0].user.name.replace(/&/g, '&').replace(/"/g, '"');
+
+ expect(vm.$el.querySelector('[data-original-title]').outerHTML).toContain(escapedName);
+ });
+
+ it('should not escape special HTML characters twice when only 1 person awarded', () => {
+ awardsMock = [...new Array(1)].map(createAwardEmoji);
+ mountComponent();
+
+ awardsMock.forEach(award => {
+ expect(findTooltip()).toContain(award.user.name);
+ });
+ });
+
+ it('should not escape special HTML characters twice when 2 people awarded', () => {
+ awardsMock = [...new Array(2)].map(createAwardEmoji);
+ mountComponent();
+
+ awardsMock.forEach(award => {
+ expect(findTooltip()).toContain(award.user.name);
+ });
+ });
+
+ it('should not escape special HTML characters twice when more than 10 people awarded', () => {
+ awardsMock = [...new Array(11)].map(createAwardEmoji);
+ mountComponent();
+
+ // Testing only the first 10 awards since 11 onward will not be displayed.
+ awardsMock.slice(0, 10).forEach(award => {
+ expect(findTooltip()).toContain(award.user.name);
+ });
+ });
+ });
+
describe('when the user cannot award emoji', () => {
beforeEach(() => {
const Component = Vue.extend(awardsNote);
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index 96aa7824ce..35283e14dc 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -14,7 +14,7 @@ describe('issue_note_form component', () => {
const createComponentWrapper = () => {
const localVue = createLocalVue();
- return shallowMount(NoteForm, {
+ return shallowMount(localVue.extend(NoteForm), {
store,
propsData: props,
// see https://gitlab.com/gitlab-org/gitlab-foss/issues/56317 for the following
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index ea1ed3da11..5e359759af 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -10,6 +10,8 @@ import mockDiffFile from '../../diffs/mock_data/diff_file';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
+const localVue = createLocalVue();
+
describe('noteable_discussion component', () => {
let store;
let wrapper;
@@ -22,8 +24,7 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- const localVue = createLocalVue();
- wrapper = mount(noteableDiscussion, {
+ wrapper = mount(localVue.extend(noteableDiscussion), {
store,
propsData: { discussion: discussionMock },
localVue,
diff --git a/spec/javascripts/notes/components/noteable_note_spec.js b/spec/javascripts/notes/components/noteable_note_spec.js
index 9420713cec..72a13afe49 100644
--- a/spec/javascripts/notes/components/noteable_note_spec.js
+++ b/spec/javascripts/notes/components/noteable_note_spec.js
@@ -18,7 +18,7 @@ describe('issue_note', () => {
store.dispatch('setNotesData', notesDataMock);
const localVue = createLocalVue();
- wrapper = shallowMount(issueNote, {
+ wrapper = shallowMount(localVue.extend(issueNote), {
store,
propsData: {
note,
diff --git a/spec/javascripts/notes/components/toggle_replies_widget_spec.js b/spec/javascripts/notes/components/toggle_replies_widget_spec.js
index 2ead8cc6e6..8485ec0262 100644
--- a/spec/javascripts/notes/components/toggle_replies_widget_spec.js
+++ b/spec/javascripts/notes/components/toggle_replies_widget_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import { note } from '../mock_data';
const deepCloneObject = obj => JSON.parse(JSON.stringify(obj));
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index e3cc025cf4..ec1f139284 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
-import Api from '~/api';
import { TEST_HOST } from 'spec/test_constants';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import Api from '~/api';
import actionsModule, * as actions from '~/notes/stores/actions';
import * as mutationTypes from '~/notes/stores/mutation_types';
import * as notesConstants from '~/notes/constants';
@@ -15,7 +16,6 @@ import {
noteableDataMock,
individualNote,
} from '../mock_data';
-import AxiosMockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
const TEST_ERROR_MESSAGE = 'Test error message';
@@ -751,29 +751,59 @@ describe('Actions Notes Store', () => {
});
describe('saveNote', () => {
- const payload = { endpoint: TEST_HOST, data: { 'note[note]': 'some text' } };
+ const flashContainer = {};
+ const payload = { endpoint: TEST_HOST, data: { 'note[note]': 'some text' }, flashContainer };
describe('if response contains errors', () => {
const res = { errors: { something: ['went wrong'] } };
+ const error = { message: 'Unprocessable entity', response: { data: res } };
it('throws an error', done => {
actions
.saveNote(
{
commit() {},
- dispatch: () => Promise.resolve(res),
+ dispatch: () => Promise.reject(error),
},
payload,
)
.then(() => done.fail('Expected error to be thrown!'))
- .catch(error => {
- expect(error.message).toBe('Failed to save comment!');
+ .catch(err => {
+ expect(err).toBe(error);
+ expect(flashSpy).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
});
+ describe('if response contains errors.base', () => {
+ const res = { errors: { base: ['something went wrong'] } };
+ const error = { message: 'Unprocessable entity', response: { data: res } };
+
+ it('sets flash alert using errors.base message', done => {
+ actions
+ .saveNote(
+ {
+ commit() {},
+ dispatch: () => Promise.reject(error),
+ },
+ { ...payload, flashContainer },
+ )
+ .then(resp => {
+ expect(resp.hasFlash).toBe(true);
+ expect(flashSpy).toHaveBeenCalledWith(
+ 'Your comment could not be submitted because something went wrong',
+ 'alert',
+ flashContainer,
+ );
+ })
+ .catch(() => done.fail('Expected success response!'))
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
describe('if response contains no errors', () => {
const res = { valid: true };
@@ -788,6 +818,7 @@ describe('Actions Notes Store', () => {
)
.then(data => {
expect(data).toBe(res);
+ expect(flashSpy).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
index 6bfb3f5ca2..9ad72e0b04 100644
--- a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
+++ b/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
@@ -1,10 +1,9 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
describe('stop_jobs_modal.vue', () => {
const props = {
url: `${gl.TEST_HOST}/stop_jobs_modal.vue/stopAll`,
diff --git a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
index 7591261225..5bad13c1ef 100644
--- a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
import eventHub from '~/pages/projects/labels/event_hub';
import axios from '~/lib/utils/axios_utils';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Promote label modal', () => {
let vm;
diff --git a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
index fe293083e4..9075c8aa97 100644
--- a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
@@ -1,11 +1,10 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
describe('delete_milestone_modal.vue', () => {
const Component = Vue.extend(deleteMilestoneModal);
const props = {
diff --git a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
index 3d25a278ce..78c0070187 100644
--- a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
import promoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub';
import axios from '~/lib/utils/axios_utils';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Promote milestone modal', () => {
let vm;
diff --git a/spec/javascripts/pdf/index_spec.js b/spec/javascripts/pdf/index_spec.js
index c746d5644e..e14f1b27f6 100644
--- a/spec/javascripts/pdf/index_spec.js
+++ b/spec/javascripts/pdf/index_spec.js
@@ -2,8 +2,8 @@ import Vue from 'vue';
import { GlobalWorkerOptions } from 'pdfjs-dist/build/pdf';
import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
-import PDFLab from '~/pdf/index.vue';
import { FIXTURES_PATH } from 'spec/test_constants';
+import PDFLab from '~/pdf/index.vue';
const pdf = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
diff --git a/spec/javascripts/pdf/page_spec.js b/spec/javascripts/pdf/page_spec.js
index efeb65acf8..bb2294e8d1 100644
--- a/spec/javascripts/pdf/page_spec.js
+++ b/spec/javascripts/pdf/page_spec.js
@@ -2,9 +2,9 @@ import Vue from 'vue';
import pdfjsLib from 'pdfjs-dist/build/pdf';
import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
-import PageComponent from '~/pdf/page/index.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { FIXTURES_PATH } from 'spec/test_constants';
+import PageComponent from '~/pdf/page/index.vue';
const testPDF = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
diff --git a/spec/javascripts/performance_bar/index_spec.js b/spec/javascripts/performance_bar/index_spec.js
index 1444d1bb3c..3957edce9e 100644
--- a/spec/javascripts/performance_bar/index_spec.js
+++ b/spec/javascripts/performance_bar/index_spec.js
@@ -1,9 +1,9 @@
+import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
+import '~/performance_bar/components/performance_bar_app.vue';
import performanceBar from '~/performance_bar';
import PerformanceBarService from '~/performance_bar/services/performance_bar_service';
-import MockAdapter from 'axios-mock-adapter';
-
describe('performance bar wrapper', () => {
let mock;
let vm;
diff --git a/spec/javascripts/persistent_user_callout_spec.js b/spec/javascripts/persistent_user_callout_spec.js
index d15758be5d..d4cb92cacf 100644
--- a/spec/javascripts/persistent_user_callout_spec.js
+++ b/spec/javascripts/persistent_user_callout_spec.js
@@ -1,7 +1,7 @@
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';
-import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
describe('PersistentUserCallout', () => {
const dismissEndpoint = '/dismiss';
diff --git a/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
index 24631cc1c8..a3957f94ca 100644
--- a/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
+++ b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue';
describe('job group dropdown component', () => {
const Component = Vue.extend(JobGroupDropdown);
diff --git a/spec/javascripts/pipelines/graph/linked_pipeline_spec.js b/spec/javascripts/pipelines/graph/linked_pipeline_spec.js
deleted file mode 100644
index 8d3abf094b..0000000000
--- a/spec/javascripts/pipelines/graph/linked_pipeline_spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import Vue from 'vue';
-import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import mockData from './linked_pipelines_mock_data';
-
-const mockPipeline = mockData.triggered[0];
-
-describe('Linked pipeline', () => {
- const Component = Vue.extend(LinkedPipelineComponent);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('rendered output', () => {
- const props = {
- pipeline: mockPipeline,
- };
-
- beforeEach(() => {
- vm = mountComponent(Component, props);
- });
-
- it('should render a list item as the containing element', () => {
- expect(vm.$el.tagName).toBe('LI');
- });
-
- it('should render a button', () => {
- const linkElement = vm.$el.querySelector('.js-linked-pipeline-content');
-
- expect(linkElement).not.toBeNull();
- });
-
- it('should render the project name', () => {
- expect(vm.$el.innerText).toContain(props.pipeline.project.name);
- });
-
- it('should render an svg within the status container', () => {
- const pipelineStatusElement = vm.$el.querySelector('.js-linked-pipeline-status');
-
- expect(pipelineStatusElement.querySelector('svg')).not.toBeNull();
- });
-
- it('should render the pipeline status icon svg', () => {
- expect(vm.$el.querySelector('.js-ci-status-icon-running')).not.toBeNull();
- expect(vm.$el.querySelector('.js-ci-status-icon-running').innerHTML).toContain('
foo/bar.md
} act = filter(exp) diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index f220ccecee..5a844fb61e 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -92,7 +92,9 @@ describe Banzai::Filter::SyntaxHighlightFilter do context "when Rouge lexing fails" do before do - allow_any_instance_of(Rouge::Lexers::Ruby).to receive(:stream_tokens).and_raise(StandardError) + allow_next_instance_of(Rouge::Lexers::Ruby) do |instance| + allow(instance).to receive(:stream_tokens).and_raise(StandardError) + end end it "highlights as plaintext" do @@ -106,7 +108,9 @@ describe Banzai::Filter::SyntaxHighlightFilter do context "when Rouge lexing fails after a retry" do before do - allow_any_instance_of(Rouge::Lexers::PlainText).to receive(:stream_tokens).and_raise(StandardError) + allow_next_instance_of(Rouge::Lexers::PlainText) do |instance| + allow(instance).to receive(:stream_tokens).and_raise(StandardError) + end end it "does not add highlighting classes" do diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index a523608fa5..aef11775e6 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -25,7 +25,9 @@ describe Banzai::ObjectRenderer do end it 'calls Banzai::ReferenceRedactor to perform redaction' do - expect_any_instance_of(Banzai::ReferenceRedactor).to receive(:redact).and_call_original + expect_next_instance_of(Banzai::ReferenceRedactor) do |instance| + expect(instance).to receive(:redact).and_call_original + end renderer.render([object], :note) end @@ -85,7 +87,9 @@ describe Banzai::ObjectRenderer do end it 'calls Banzai::ReferenceRedactor to perform redaction' do - expect_any_instance_of(Banzai::ReferenceRedactor).to receive(:redact).and_call_original + expect_next_instance_of(Banzai::ReferenceRedactor) do |instance| + expect(instance).to receive(:redact).and_call_original + end renderer.render([cacheless_thing], :title) end diff --git a/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb new file mode 100644 index 0000000000..9832b132b5 --- /dev/null +++ b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Banzai::Pipeline::BroadcastMessagePipeline do + before do + stub_commonmark_sourcepos_disabled + end + + subject { described_class.to_html(exp, project: spy) } + + context "allows `a` elements" do + let(:exp) { "Link" } + + it { is_expected.to eq("#{exp}
") } + end + + context "allows `br` elements" do + let(:exp) { "Hello#{exp}
") } + end +end diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 26f2b0b0ac..e1814ea403 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -72,14 +72,14 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "[Page](./page)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page\"") end it "rewrites file links to be at the scope of the current directory" do markdown = "[Link to Page](./page.md)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page.md\"") end end @@ -88,14 +88,14 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "[Link to Page](../page)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/page\"") end it "rewrites file links to be at the scope of the parent directory" do markdown = "[Link to Page](../page.md)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page.md\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/page.md\"") end end @@ -104,14 +104,14 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "[Link to Page](./subdirectory/page)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/subdirectory/page\"") end it "rewrites file links to be at the scope of the sub-directory" do markdown = "[Link to Page](./subdirectory/page.md)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page.md\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/subdirectory/page.md\"") end end @@ -120,35 +120,35 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "[Link to Page](page)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page\"") end it 'rewrites non-file links (with spaces) to be at the scope of the wiki root' do markdown = "[Link to Page](page slug)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page%20slug\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page%20slug\"") end it "rewrites file links to be at the scope of the current directory" do markdown = "[Link to Page](page.md)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page.md\"") end it 'rewrites links with anchor' do markdown = '[Link to Header](start-page#title)' output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start-page#title\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/start-page#title\"") end it 'rewrites links (with spaces) with anchor' do markdown = '[Link to Header](start page#title)' output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start%20page#title\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/start%20page#title\"") end end @@ -157,14 +157,14 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "[Link to Page](/page)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page\"") end it 'rewrites file links to be at the scope of the wiki root' do markdown = "[Link to Page](/page.md)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page.md\"") + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page.md\"") end end end @@ -270,28 +270,28 @@ describe Banzai::Pipeline::WikiPipeline do markdown = "![video_file](video_file_name.mp4)" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include('