diff options
Diffstat (limited to 'spec/frontend')
10 files changed, 281 insertions, 55 deletions
diff --git a/spec/frontend/alert_management/components/alert_management_detail_spec.js b/spec/frontend/alert_management/components/alert_management_detail_spec.js index 2758014aaa7..5234be0bf07 100644 --- a/spec/frontend/alert_management/components/alert_management_detail_spec.js +++ b/spec/frontend/alert_management/components/alert_management_detail_spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; import AlertDetails from '~/alert_management/components/alert_details.vue'; @@ -11,18 +11,20 @@ describe('AlertDetails', () => { const newIssuePath = 'root/alerts/-/issues/new'; function mountComponent({ - data = { alert: {} }, + data, createIssueFromAlertEnabled = false, loading = false, + mountMethod = shallowMount, + stubs = {}, } = {}) { - wrapper = shallowMount(AlertDetails, { + wrapper = mountMethod(AlertDetails, { propsData: { alertId: 'alertId', projectPath: 'projectPath', newIssuePath, }, data() { - return data; + return { alert: { ...mockAlert }, ...data }; }, provide: { glFeatures: { createIssueFromAlertEnabled }, @@ -36,6 +38,7 @@ describe('AlertDetails', () => { }, }, }, + stubs, }); } @@ -149,5 +152,33 @@ describe('AlertDetails', () => { expect(wrapper.find(GlAlert).exists()).toBe(false); }); }); + + describe('header', () => { + const findHeader = () => wrapper.find('[data-testid="alert-header"]'); + const stubs = { TimeAgoTooltip: '<span>now</span>' }; + + describe('individual header fields', () => { + describe.each` + severity | createdAt | monitoringTool | result + ${'MEDIUM'} | ${'2020-04-17T23:18:14.996Z'} | ${null} | ${'Medium • Reported now'} + ${'INFO'} | ${'2020-04-17T23:18:14.996Z'} | ${'Datadog'} | ${'Info • Reported now by Datadog'} + `( + `When severity=$severity, createdAt=$createdAt, monitoringTool=$monitoringTool`, + ({ severity, createdAt, monitoringTool, result }) => { + beforeEach(() => { + mountComponent({ + data: { alert: { ...mockAlert, severity, createdAt, monitoringTool } }, + mountMethod: mount, + stubs, + }); + }); + + it('header text is shown correctly', () => { + expect(findHeader().text()).toBe(result); + }); + }, + ); + }); + }); }); }); diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js index 23da4df188b..597574bdeed 100644 --- a/spec/frontend/ide/components/new_dropdown/modal_spec.js +++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js @@ -91,22 +91,31 @@ describe('new file modal component', () => { expect(vm.entryName).toBe('test-path'); }); - it('updated name', () => { - vm.name = 'index.js'; + it('does not reset entryName to its old value if empty', () => { + vm.entryName = 'hello'; + vm.entryName = ''; - expect(vm.entryName).toBe('index.js'); + expect(vm.entryName).toBe(''); + }); + }); + + describe('open', () => { + it('sets entryName to path provided if modalType is rename', () => { + vm.open('rename', 'test-path'); + + expect(vm.entryName).toBe('test-path'); }); - it('removes leading/trailing spaces when found in the new name', () => { - vm.entryName = ' index.js '; + it("appends '/' to the path if modalType isn't rename", () => { + vm.open('blob', 'test-path'); - expect(vm.entryName).toBe('index.js'); + expect(vm.entryName).toBe('test-path/'); }); - it('does not remove internal spaces in the file name', () => { - vm.entryName = ' In Praise of Idleness.txt '; + it('leaves entryName blank if no path is provided', () => { + vm.open('blob'); - expect(vm.entryName).toBe('In Praise of Idleness.txt'); + expect(vm.entryName).toBe(''); }); }); }); diff --git a/spec/frontend/monitoring/components/variables_section_spec.js b/spec/frontend/monitoring/components/variables_section_spec.js index 7271beea50a..51c0e192c58 100644 --- a/spec/frontend/monitoring/components/variables_section_spec.js +++ b/spec/frontend/monitoring/components/variables_section_spec.js @@ -15,8 +15,8 @@ describe('Metrics dashboard/variables section component', () => { let store; let wrapper; const sampleVariables = { - label1: 'pod', - label2: 'main', + 'var-label1': 'pod', + 'var-label2': 'main', }; const createShallowWrapper = () => { diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js index 2fa88dfa87a..a8443c08b00 100644 --- a/spec/frontend/monitoring/mock_data.js +++ b/spec/frontend/monitoring/mock_data.js @@ -642,7 +642,7 @@ const generateMockTemplatingData = data => { const responseForSimpleTextVariable = { simpleText: { - label: 'simpleText', + label: 'var-simpleText', type: 'text', value: 'Simple text', }, @@ -650,7 +650,7 @@ const responseForSimpleTextVariable = { const responseForAdvTextVariable = { advText: { - label: 'Variable 4', + label: 'var-Variable 4', type: 'text', value: 'default', }, @@ -658,7 +658,7 @@ const responseForAdvTextVariable = { const responseForSimpleCustomVariable = { simpleCustom: { - label: 'simpleCustom', + label: 'var-simpleCustom', options: [ { default: false, @@ -682,7 +682,7 @@ const responseForSimpleCustomVariable = { const responseForAdvancedCustomVariableWithoutOptions = { advCustomWithoutOpts: { - label: 'advCustomWithoutOpts', + label: 'var-advCustomWithoutOpts', options: [], type: 'custom', }, @@ -690,7 +690,7 @@ const responseForAdvancedCustomVariableWithoutOptions = { const responseForAdvancedCustomVariableWithoutLabel = { advCustomWithoutLabel: { - label: 'advCustomWithoutLabel', + label: 'var-advCustomWithoutLabel', options: [ { default: false, @@ -710,7 +710,7 @@ const responseForAdvancedCustomVariableWithoutLabel = { const responseForAdvancedCustomVariable = { ...responseForSimpleCustomVariable, advCustomNormal: { - label: 'Advanced Var', + label: 'var-Advanced Var', options: [ { default: false, diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js index f07ae4c5a1e..e3ee9ffb2bc 100644 --- a/spec/frontend/monitoring/store/getters_spec.js +++ b/spec/frontend/monitoring/store/getters_spec.js @@ -327,7 +327,8 @@ describe('Monitoring store Getters', () => { describe('getCustomVariablesArray', () => { let state; const sampleVariables = { - label1: 'pod', + 'var-label1': 'pod', + 'var-label2': 'env', }; beforeEach(() => { @@ -340,7 +341,7 @@ describe('Monitoring store Getters', () => { mutations[types.SET_PROM_QUERY_VARIABLES](state, sampleVariables); const variablesArray = getters.getCustomVariablesArray(state); - expect(variablesArray).toEqual(['label1', 'pod']); + expect(variablesArray).toEqual(['label1', 'pod', 'label2', 'env']); }); it('transforms the promVariables object to an empty array when no keys are present', () => { diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js index 21597033e0a..52fd776e67e 100644 --- a/spec/frontend/monitoring/utils_spec.js +++ b/spec/frontend/monitoring/utils_spec.js @@ -192,9 +192,10 @@ describe('monitoring/utils', () => { direction: 'left', anchor: 'top', pod: 'POD', + 'var-pod': 'POD', }); - expect(promCustomVariablesFromUrl()).toEqual(expect.objectContaining({ pod: 'POD' })); + expect(promCustomVariablesFromUrl()).toEqual(expect.objectContaining({ 'var-pod': 'POD' })); }); it('returns an empty object when no custom variables are present', () => { 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 f7b1f041ef2..dd24ecf707d 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 @@ -2,10 +2,7 @@ import Vue from 'vue'; import { mount } from '@vue/test-utils'; import { formatDate } from '~/lib/utils/datetime_utility'; import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue'; -import { - defaultAssignees, - defaultMilestone, -} from '../../../../javascripts/vue_shared/components/issue/related_issuable_mock_data'; +import { defaultAssignees, defaultMilestone } from './related_issuable_mock_data'; describe('RelatedIssuableItem', () => { let wrapper; diff --git a/spec/frontend/vue_shared/components/markdown/suggestions_spec.js b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js new file mode 100644 index 00000000000..34ccdf38b00 --- /dev/null +++ b/spec/frontend/vue_shared/components/markdown/suggestions_spec.js @@ -0,0 +1,102 @@ +import Vue from 'vue'; +import SuggestionsComponent from '~/vue_shared/components/markdown/suggestions.vue'; + +const MOCK_DATA = { + suggestions: [ + { + id: 1, + appliable: true, + applied: false, + current_user: { + can_apply: true, + }, + diff_lines: [ + { + can_receive_suggestion: false, + line_code: null, + meta_data: null, + new_line: null, + old_line: 5, + rich_text: '-test', + text: '-test', + type: 'old', + }, + { + can_receive_suggestion: true, + line_code: null, + meta_data: null, + new_line: 5, + old_line: null, + rich_text: '+new test', + text: '+new test', + type: 'new', + }, + ], + }, + ], + noteHtml: ` + <div class="suggestion"> + <div class="line">-oldtest</div> + </div> + <div class="suggestion"> + <div class="line">+newtest</div> + </div> + `, + isApplied: false, + helpPagePath: 'path_to_docs', +}; + +describe('Suggestion component', () => { + let vm; + let diffTable; + + beforeEach(done => { + const Component = Vue.extend(SuggestionsComponent); + + vm = new Component({ + propsData: MOCK_DATA, + }).$mount(); + + diffTable = vm.generateDiff(0).$mount().$el; + + jest.spyOn(vm, 'renderSuggestions').mockImplementation(() => {}); + vm.renderSuggestions(); + Vue.nextTick(done); + }); + + describe('mounted', () => { + it('renders a flash container', () => { + expect(vm.$el.querySelector('.js-suggestions-flash')).not.toBeNull(); + }); + + it('renders a container for suggestions', () => { + expect(vm.$refs.container).not.toBeNull(); + }); + + it('renders suggestions', () => { + expect(vm.renderSuggestions).toHaveBeenCalled(); + expect(vm.$el.innerHTML.includes('oldtest')).toBe(true); + expect(vm.$el.innerHTML.includes('newtest')).toBe(true); + }); + }); + + describe('generateDiff', () => { + it('generates a diff table', () => { + expect(diffTable.querySelector('.md-suggestion-diff')).not.toBeNull(); + }); + + it('generates a diff table that contains contents the suggested lines', () => { + MOCK_DATA.suggestions[0].diff_lines.forEach(line => { + const text = line.text.substring(1); + + expect(diffTable.innerHTML.includes(text)).toBe(true); + }); + }); + + it('generates a diff table with the correct line number for each suggested line', () => { + const lines = diffTable.querySelectorAll('.old_line'); + + expect(parseInt([...lines][0].innerHTML, 10)).toBe(5); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js new file mode 100644 index 00000000000..29bced394dc --- /dev/null +++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js @@ -0,0 +1,112 @@ +import Vue from 'vue'; +import { head } from 'lodash'; + +import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui'; +import { mount, createLocalVue } from '@vue/test-utils'; +import { trimText } from 'helpers/text_helper'; +import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue'; +import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue'; + +const localVue = createLocalVue(); + +describe('ProjectSelector component', () => { + let wrapper; + let vm; + const allProjects = getJSONFixture('static/projects.json'); + const searchResults = allProjects.slice(0, 5); + let selected = []; + selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8)); + + const findSearchInput = () => wrapper.find(GlSearchBoxByType).find('input'); + + beforeEach(() => { + wrapper = mount(Vue.extend(ProjectSelector), { + localVue, + propsData: { + projectSearchResults: searchResults, + selectedProjects: selected, + showNoResultsMessage: false, + showMinimumSearchQueryMessage: false, + showLoadingIndicator: false, + showSearchErrorMessage: false, + }, + attachToDocument: true, + }); + + ({ vm } = wrapper); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders the search results', () => { + expect(wrapper.findAll('.js-project-list-item').length).toBe(5); + }); + + it(`triggers a search when the search input value changes`, () => { + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + const query = 'my test query!'; + const searchInput = findSearchInput(); + + searchInput.setValue(query); + searchInput.trigger('input'); + + expect(vm.$emit).toHaveBeenCalledWith('searched', query); + }); + + it(`includes a placeholder in the search box`, () => { + const searchInput = findSearchInput(); + + expect(searchInput.attributes('placeholder')).toBe('Search your projects'); + }); + + it(`triggers a "bottomReached" event when user has scrolled to the bottom of the list`, () => { + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + wrapper.find(GlInfiniteScroll).vm.$emit('bottomReached'); + + expect(vm.$emit).toHaveBeenCalledWith('bottomReached'); + }); + + it(`triggers a "projectClicked" event when a project is clicked`, () => { + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + wrapper.find(ProjectListItem).vm.$emit('click', head(searchResults)); + + expect(vm.$emit).toHaveBeenCalledWith('projectClicked', head(searchResults)); + }); + + it(`shows a "no results" message if showNoResultsMessage === true`, () => { + wrapper.setProps({ showNoResultsMessage: true }); + + return vm.$nextTick().then(() => { + const noResultsEl = wrapper.find('.js-no-results-message'); + + expect(noResultsEl.exists()).toBe(true); + expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search'); + }); + }); + + it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, () => { + wrapper.setProps({ showMinimumSearchQueryMessage: true }); + + return vm.$nextTick().then(() => { + const minimumSearchEl = wrapper.find('.js-minimum-search-query-message'); + + expect(minimumSearchEl.exists()).toBe(true); + expect(trimText(minimumSearchEl.text())).toEqual('Enter at least three characters to search'); + }); + }); + + it(`shows a error message if showSearchErrorMessage === true`, () => { + wrapper.setProps({ showSearchErrorMessage: true }); + + return vm.$nextTick().then(() => { + const errorMessageEl = wrapper.find('.js-search-error-message'); + + expect(errorMessageEl.exists()).toBe(true); + expect(trimText(errorMessageEl.text())).toEqual( + 'Something went wrong, unable to search projects', + ); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_svg_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_svg_spec.js deleted file mode 100644 index ee6c2e2cc46..00000000000 --- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_svg_spec.js +++ /dev/null @@ -1,27 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import UserAvatarSvg from '~/vue_shared/components/user_avatar/user_avatar_svg.vue'; - -describe('User Avatar Svg Component', () => { - describe('Initialization', () => { - let wrapper; - - beforeEach(() => { - wrapper = shallowMount(UserAvatarSvg, { - propsData: { - size: 99, - svg: - '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M1.707 15.707C1.077z"/></svg>', - }, - }); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('should have <svg> as a child element', () => { - expect(wrapper.element.tagName).toEqual('svg'); - expect(wrapper.html()).toContain('<path'); - }); - }); -}); |