diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-09 09:07:45 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-09 09:07:45 +0000 |
commit | f4186a753b86625a83e8499af14b5badd63a2ac2 (patch) | |
tree | b960dd9f4255e9eee9f87d28e853f163836aa4c5 /spec/frontend | |
parent | 0221116862ee66024a03492b4fbbe4e069d84303 (diff) | |
download | gitlab-ce-f4186a753b86625a83e8499af14b5badd63a2ac2.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
10 files changed, 340 insertions, 111 deletions
diff --git a/spec/frontend/blob/components/__snapshots__/blob_edit_content_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_edit_content_spec.js.snap new file mode 100644 index 00000000000..0409b118222 --- /dev/null +++ b/spec/frontend/blob/components/__snapshots__/blob_edit_content_spec.js.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Blob Header Editing rendering matches the snapshot 1`] = ` +<div + class="file-content code" +> + <pre + data-editor-loading="" + id="editor" + > + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + </pre> +</div> +`; diff --git a/spec/frontend/blob/components/blob_edit_content_spec.js b/spec/frontend/blob/components/blob_edit_content_spec.js new file mode 100644 index 00000000000..eff53fe7ce9 --- /dev/null +++ b/spec/frontend/blob/components/blob_edit_content_spec.js @@ -0,0 +1,81 @@ +import { shallowMount } from '@vue/test-utils'; +import BlobEditContent from '~/blob/components/blob_edit_content.vue'; +import { initEditorLite } from '~/blob/utils'; +import { nextTick } from 'vue'; + +jest.mock('~/blob/utils', () => ({ + initEditorLite: jest.fn(), +})); + +describe('Blob Header Editing', () => { + let wrapper; + const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + const fileName = 'lorem.txt'; + + function createComponent() { + wrapper = shallowMount(BlobEditContent, { + propsData: { + value, + fileName, + }, + }); + } + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('rendering', () => { + it('matches the snapshot', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it('renders content', () => { + expect(wrapper.text()).toContain(value); + }); + }); + + describe('functionality', () => { + it('initialises Editor Lite', () => { + const el = wrapper.find({ ref: 'editor' }).element; + expect(initEditorLite).toHaveBeenCalledWith({ + el, + blobPath: fileName, + blobContent: value, + }); + }); + + it('reacts to the changes in fileName', () => { + wrapper.vm.editor = { + updateModelLanguage: jest.fn(), + }; + + const newFileName = 'ipsum.txt'; + + wrapper.setProps({ + fileName: newFileName, + }); + + return nextTick().then(() => { + expect(wrapper.vm.editor.updateModelLanguage).toHaveBeenCalledWith(newFileName); + }); + }); + + it('emits input event when the blob content is changed', () => { + const editorEl = wrapper.find({ ref: 'editor' }); + wrapper.vm.editor = { + getValue: jest.fn().mockReturnValue(value), + }; + + editorEl.trigger('focusout'); + + return nextTick().then(() => { + expect(wrapper.emitted().input[0]).toEqual([value]); + }); + }); + }); +}); diff --git a/spec/frontend/blob/utils_spec.js b/spec/frontend/blob/utils_spec.js new file mode 100644 index 00000000000..39a73aae444 --- /dev/null +++ b/spec/frontend/blob/utils_spec.js @@ -0,0 +1,95 @@ +import Editor from '~/editor/editor_lite'; +import * as utils from '~/blob/utils'; + +const mockCreateMonacoInstance = jest.fn(); +jest.mock('~/editor/editor_lite', () => { + return jest.fn().mockImplementation(() => { + return { createInstance: mockCreateMonacoInstance }; + }); +}); + +const mockCreateAceInstance = jest.fn(); +global.ace = { + edit: mockCreateAceInstance, +}; + +describe('Blob utilities', () => { + beforeEach(() => { + Editor.mockClear(); + }); + + describe('initEditorLite', () => { + let editorEl; + const blobPath = 'foo.txt'; + const blobContent = 'Foo bar'; + + beforeEach(() => { + setFixtures('<div id="editor"></div>'); + editorEl = document.getElementById('editor'); + }); + + describe('Monaco editor', () => { + let origProp; + + beforeEach(() => { + origProp = window.gon; + window.gon = { + features: { + monacoSnippets: true, + }, + }; + }); + + afterEach(() => { + window.gon = origProp; + }); + + it('initializes the Editor Lite', () => { + utils.initEditorLite({ el: editorEl }); + expect(Editor).toHaveBeenCalled(); + }); + + it('creates the instance with the passed parameters', () => { + utils.initEditorLite({ el: editorEl }); + expect(mockCreateMonacoInstance.mock.calls[0]).toEqual([ + { + el: editorEl, + blobPath: undefined, + blobContent: undefined, + }, + ]); + + utils.initEditorLite({ el: editorEl, blobPath, blobContent }); + expect(mockCreateMonacoInstance.mock.calls[1]).toEqual([ + { + el: editorEl, + blobPath, + blobContent, + }, + ]); + }); + }); + describe('ACE editor', () => { + let origProp; + + beforeEach(() => { + origProp = window.gon; + window.gon = { + features: { + monacoSnippets: false, + }, + }; + }); + + afterEach(() => { + window.gon = origProp; + }); + + it('does not initialize the Editor Lite', () => { + utils.initEditorLite({ el: editorEl }); + expect(Editor).not.toHaveBeenCalled(); + expect(mockCreateAceInstance).toHaveBeenCalledWith(editorEl); + }); + }); + }); +}); diff --git a/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js b/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js deleted file mode 100644 index 53e670e76da..00000000000 --- a/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js +++ /dev/null @@ -1,40 +0,0 @@ -import { GlLink } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import IssueCardInnerScopedLabel from '~/boards/components/issue_card_inner_scoped_label.vue'; - -describe('IssueCardInnerScopedLabel Component', () => { - let wrapper; - - beforeEach(() => { - wrapper = shallowMount(IssueCardInnerScopedLabel, { - propsData: { - label: { title: 'Foo::Bar', description: 'Some Random Description' }, - labelStyle: { background: 'white', color: 'black' }, - scopedLabelsDocumentationLink: '/docs-link', - }, - }); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('should render label title', () => { - expect(wrapper.find('.color-label').text()).toBe('Foo::Bar'); - }); - - it('should render question mark symbol', () => { - expect(wrapper.find('.fa-question-circle').exists()).toBe(true); - }); - - it('should render label style provided', () => { - const label = wrapper.find('.color-label'); - - expect(label.attributes('style')).toContain('background: white;'); - expect(label.attributes('style')).toContain('color: black;'); - }); - - it('should render the docs link', () => { - expect(wrapper.find(GlLink).attributes('href')).toBe('/docs-link'); - }); -}); diff --git a/spec/frontend/boards/issue_card_spec.js b/spec/frontend/boards/issue_card_spec.js index 1fd2b417aba..f78e4dad2c0 100644 --- a/spec/frontend/boards/issue_card_spec.js +++ b/spec/frontend/boards/issue_card_spec.js @@ -8,6 +8,7 @@ import '~/boards/models/list'; import IssueCardInner from '~/boards/components/issue_card_inner.vue'; import { listObj } from '../../javascripts/boards/mock_data'; import store from '~/boards/stores'; +import { GlLabel } from '@gitlab/ui'; describe('Issue card component', () => { const user = new ListAssignee({ @@ -20,7 +21,7 @@ describe('Issue card component', () => { const label1 = new ListLabel({ id: 3, title: 'testing 123', - color: 'blue', + color: '#000CFF', text_color: 'white', description: 'test', }); @@ -50,6 +51,9 @@ describe('Issue card component', () => { rootPath: '/', }, store, + stubs: { + GlLabel: true, + }, }); }); @@ -290,25 +294,11 @@ describe('Issue card component', () => { }); it('does not render list label but renders all other labels', () => { - expect(wrapper.findAll('.badge').length).toBe(1); - }); - - it('renders label', () => { - const nodes = wrapper.findAll('.badge').wrappers.map(label => label.attributes('title')); - - expect(nodes.includes(label1.description)).toBe(true); - }); - - it('sets label description as title', () => { - expect(wrapper.find('.badge').attributes('title')).toContain(label1.description); - }); - - it('sets background color of button', () => { - const nodes = wrapper - .findAll('.badge') - .wrappers.map(label => label.element.style.backgroundColor); - - expect(nodes.includes(label1.color)).toBe(true); + expect(wrapper.findAll(GlLabel).length).toBe(1); + const label = wrapper.find(GlLabel); + expect(label.props('title')).toEqual(label1.title); + expect(label.props('description')).toEqual(label1.description); + expect(label.props('backgroundColor')).toEqual(label1.color); }); it('does not render label if label does not have an ID', done => { @@ -321,7 +311,7 @@ describe('Issue card component', () => { wrapper.vm .$nextTick() .then(() => { - expect(wrapper.findAll('.badge').length).toBe(1); + expect(wrapper.findAll(GlLabel).length).toBe(1); expect(wrapper.text()).not.toContain('closed'); done(); }) diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js index 825bc7813a5..85c86b2c0a9 100644 --- a/spec/frontend/clusters_list/components/clusters_spec.js +++ b/spec/frontend/clusters_list/components/clusters_spec.js @@ -1,7 +1,8 @@ +import Vuex from 'vuex'; import { createLocalVue, mount } from '@vue/test-utils'; import { GlTable, GlLoadingIcon } from '@gitlab/ui'; import Clusters from '~/clusters_list/components/clusters.vue'; -import Vuex from 'vuex'; +import mockData from '../mock_data'; const localVue = createLocalVue(); localVue.use(Vuex); @@ -11,9 +12,10 @@ describe('Clusters', () => { const findTable = () => wrapper.find(GlTable); const findLoader = () => wrapper.find(GlLoadingIcon); + const findStatuses = () => findTable().findAll('.js-status'); const mountComponent = _state => { - const state = { clusters: [], endpoint: 'some/endpoint', ..._state }; + const state = { clusters: mockData, endpoint: 'some/endpoint', ..._state }; const store = new Vuex.Store({ state, }); @@ -52,4 +54,25 @@ describe('Clusters', () => { expect(findTable().classes()).toContain('b-table-stacked-md'); }); }); + + describe('cluster status', () => { + it.each` + statusName | className | lineNumber + ${'disabled'} | ${'disabled'} | ${0} + ${'unreachable'} | ${'bg-danger'} | ${1} + ${'authentication_failure'} | ${'bg-warning'} | ${2} + ${'deleting'} | ${null} | ${3} + ${'connected'} | ${'bg-success'} | ${4} + `('renders a status for each cluster', ({ statusName, className, lineNumber }) => { + const statuses = findStatuses(); + const status = statuses.at(lineNumber); + if (statusName !== 'deleting') { + const statusIndicator = status.find('.cluster-status-indicator'); + expect(statusIndicator.exists()).toBe(true); + expect(statusIndicator.classes()).toContain(className); + } else { + expect(status.find(GlLoadingIcon).exists()).toBe(true); + } + }); + }); }); diff --git a/spec/frontend/clusters_list/mock_data.js b/spec/frontend/clusters_list/mock_data.js new file mode 100644 index 00000000000..0a49c2e9f43 --- /dev/null +++ b/spec/frontend/clusters_list/mock_data.js @@ -0,0 +1,37 @@ +export default [ + { + name: 'My Cluster 1', + environmentScope: '*', + size: '3', + clusterType: 'group_type', + status: 'disabled', + }, + { + name: 'My Cluster 2', + environmentScope: 'development', + size: '12', + clusterType: 'project_type', + status: 'unreachable', + }, + { + name: 'My Cluster 3', + environmentScope: 'development', + size: '12', + clusterType: 'project_type', + status: 'authentication_failure', + }, + { + name: 'My Cluster 4', + environmentScope: 'production', + size: '12', + clusterType: 'project_type', + status: 'deleting', + }, + { + name: 'My Cluster 5', + environmentScope: 'development', + size: '12', + clusterType: 'project_type', + status: 'connected', + }, +]; diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap new file mode 100644 index 00000000000..b1bbe2a9710 --- /dev/null +++ b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Snippet Blob Edit component rendering matches the snapshot 1`] = ` +<div + class="form-group file-editor" +> + <label> + File + </label> + + <div + class="file-holder snippet" + > + <blob-header-edit-stub + value="lorem.txt" + /> + + <blob-content-edit-stub + filename="lorem.txt" + value="Lorem ipsum dolor sit amet, consectetur adipiscing elit." + /> + </div> +</div> +`; diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js new file mode 100644 index 00000000000..42b49c50c75 --- /dev/null +++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js @@ -0,0 +1,40 @@ +import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue'; +import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue'; +import BlobContentEdit from '~/blob/components/blob_edit_content.vue'; +import { shallowMount } from '@vue/test-utils'; + +jest.mock('~/blob/utils', () => jest.fn()); + +describe('Snippet Blob Edit component', () => { + let wrapper; + const content = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; + const fileName = 'lorem.txt'; + + function createComponent() { + wrapper = shallowMount(SnippetBlobEdit, { + propsData: { + content, + fileName, + }, + }); + } + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('rendering', () => { + it('matches the snapshot', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it('renders required components', () => { + expect(wrapper.contains(BlobHeaderEdit)).toBe(true); + expect(wrapper.contains(BlobContentEdit)).toBe(true); + }); + }); +}); 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 54ad96073c8..06355c0dd65 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,31 +1,26 @@ 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 { GlLabel } from '@gitlab/ui'; 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, -) => { - labels.forEach(label => Object.assign(label, labelStyles)); - - return mount(DropdownValueComponent, { +) => + mount(DropdownValueComponent, { propsData: { labels, labelFilterBasePath, enableScopedLabels: true, }, + stubs: { + GlLabel: true, + }, }); -}; describe('DropdownValueComponent', () => { let vm; @@ -56,24 +51,17 @@ describe('DropdownValueComponent', () => { describe('methods', () => { describe('labelFilterUrl', () => { it('returns URL string starting with labelFilterBasePath and encoded label.title', () => { - expect(vm.find(DropdownValueScopedLabel).props('labelFilterUrl')).toBe( - '/gitlab-org/my-project/issues?label_name[]=Foo%3A%3ABar', + expect(vm.find(GlLabel).props('target')).toBe( + '/gitlab-org/my-project/issues?label_name[]=Foo%20Label', ); }); }); - describe('labelStyle', () => { - it('returns object with `color` & `backgroundColor` properties from label.textColor & label.color', () => { - 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.findAll(DropdownValueScopedLabel).length).toEqual(1); + const labels = vm.findAll(GlLabel); + expect(labels.length).toEqual(2); + expect(labels.at(1).props('scoped')).toBe(true); }); }); }); @@ -95,33 +83,10 @@ describe('DropdownValueComponent', () => { vmEmptyLabels.destroy(); }); - it('renders label element with filter URL', () => { - 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.find('a span.badge.color-label'); + it('renders DropdownValueComponent element', () => { + const labelEl = vm.find(GlLabel); 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.find('span.scoped-label-wrapper').exists()).toBe(true); - }); - - it('renders anchor tag containing question icon', () => { - const anchor = vm.find('.scoped-label-wrapper a.scoped-label'); - - expect(anchor.exists()).toBe(true); - expect(anchor.find('i.fa-question-circle').exists()).toBe(true); - }); }); }); }); |