diff options
Diffstat (limited to 'spec/javascripts/vue_mr_widget')
18 files changed, 860 insertions, 767 deletions
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js index a750bc78f36..f14d5f6f76c 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js @@ -1,39 +1,39 @@ import Vue from 'vue'; -import authorComponent from '~/vue_merge_request_widget/components/mr_widget_author'; - -const author = { - webUrl: 'http://foo.bar', - avatarUrl: 'http://gravatar.com/foo', - name: 'fatihacet', -}; -const createComponent = () => { - const Component = Vue.extend(authorComponent); - - return new Component({ - el: document.createElement('div'), - propsData: { author }, - }); -}; +import authorComponent from '~/vue_merge_request_widget/components/mr_widget_author.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('MRWidgetAuthor', () => { - describe('props', () => { - it('should have props', () => { - const authorProp = authorComponent.props.author; + let vm; + + beforeEach(() => { + const Component = Vue.extend(authorComponent); + + vm = mountComponent(Component, { + author: { + name: 'Administrator', + username: 'root', + webUrl: 'http://localhost:3000/root', + avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + }, - expect(authorProp).toBeDefined(); - expect(authorProp.type instanceof Object).toBeTruthy(); - expect(authorProp.required).toBeTruthy(); }); }); - describe('template', () => { - it('should have correct elements', () => { - const el = createComponent().$el; + afterEach(() => { + vm.$destroy(); + }); - expect(el.tagName).toEqual('A'); - expect(el.getAttribute('href')).toEqual(author.webUrl); - expect(el.querySelector('img').getAttribute('src')).toEqual(author.avatarUrl); - expect(el.querySelector('.author').innerText.trim()).toEqual(author.name); - }); + it('renders link with the author web url', () => { + expect(vm.$el.getAttribute('href')).toEqual('http://localhost:3000/root'); + }); + + it('renders image with avatar url', () => { + expect( + vm.$el.querySelector('img').getAttribute('src'), + ).toEqual('http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon'); + }); + + it('renders author name', () => { + expect(vm.$el.textContent.trim()).toEqual('Administrator'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js index 515ddcbb875..8c55622b15e 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js @@ -1,61 +1,40 @@ import Vue from 'vue'; -import authorTimeComponent from '~/vue_merge_request_widget/components/mr_widget_author_time'; - -const props = { - actionText: 'Merged by', - author: { - webUrl: 'http://foo.bar', - avatarUrl: 'http://gravatar.com/foo', - name: 'fatihacet', - }, - dateTitle: '2017-03-23T23:02:00.807Z', - dateReadable: '12 hours ago', -}; -const createComponent = () => { - const Component = Vue.extend(authorTimeComponent); - - return new Component({ - el: document.createElement('div'), - propsData: props, - }); -}; +import authorTimeComponent from '~/vue_merge_request_widget/components/mr_widget_author_time.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('MRWidgetAuthorTime', () => { - describe('props', () => { - it('should have props', () => { - const { actionText, author, dateTitle, dateReadable } = authorTimeComponent.props; - const ActionTextClass = actionText.type; - const DateTitleClass = dateTitle.type; - const DateReadableClass = dateReadable.type; - - expect(new ActionTextClass() instanceof String).toBeTruthy(); - expect(actionText.required).toBeTruthy(); - - expect(author.type instanceof Object).toBeTruthy(); - expect(author.required).toBeTruthy(); - - expect(new DateTitleClass() instanceof String).toBeTruthy(); - expect(dateTitle.required).toBeTruthy(); - - expect(new DateReadableClass() instanceof String).toBeTruthy(); - expect(dateReadable.required).toBeTruthy(); + let vm; + + beforeEach(() => { + const Component = Vue.extend(authorTimeComponent); + + vm = mountComponent(Component, { + actionText: 'Merged by', + author: { + name: 'Administrator', + username: 'root', + webUrl: 'http://localhost:3000/root', + avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + }, + dateTitle: '2017-03-23T23:02:00.807Z', + dateReadable: '12 hours ago', }); }); - describe('components', () => { - it('should have components', () => { - expect(authorTimeComponent.components['mr-widget-author']).toBeDefined(); - }); + afterEach(() => { + vm.$destroy(); + }); + + it('renders provided action text', () => { + expect(vm.$el.textContent).toContain('Merged by'); }); - describe('template', () => { - it('should have correct elements', () => { - const el = createComponent().$el; + it('renders author', () => { + expect(vm.$el.textContent).toContain('Administrator'); + }); - expect(el.tagName).toEqual('H4'); - expect(el.querySelector('a').getAttribute('href')).toEqual(props.author.webUrl); - expect(el.querySelector('time').innerText).toContain(props.dateReadable); - expect(el.querySelector('time').getAttribute('title')).toEqual(props.dateTitle); - }); + it('renders provided time', () => { + expect(vm.$el.querySelector('time').getAttribute('title')).toEqual('2017-03-23T23:02:00.807Z'); + expect(vm.$el.querySelector('time').textContent.trim()).toEqual('12 hours ago'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js index 06f89fabf42..13e5595bbfc 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js @@ -1,104 +1,219 @@ import Vue from 'vue'; -import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header'; - -const createComponent = (mr) => { - const Component = Vue.extend(headerComponent); - return new Component({ - el: document.createElement('div'), - propsData: { mr }, - }); -}; +import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('MRWidgetHeader', () => { - describe('props', () => { - it('should have props', () => { - const { mr } = headerComponent.props; + let vm; + let Component; - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - }); + beforeEach(() => { + Component = Vue.extend(headerComponent); + }); + + afterEach(() => { + vm.$destroy(); }); describe('computed', () => { - let vm; - beforeEach(() => { - vm = createComponent({ - divergedCommitsCount: 12, - sourceBranch: 'mr-widget-refactor', - sourceBranchLink: '/foo/bar/mr-widget-refactor', - targetBranch: 'master', + describe('shouldShowCommitsBehindText', () => { + it('return true when there are divergedCommitsCount', () => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 12, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', + targetBranch: 'master', + } }); + + expect(vm.shouldShowCommitsBehindText).toEqual(true); + }); + + it('returns false where there are no divergedComits count', () => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 0, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', + targetBranch: 'master', + } }); + expect(vm.shouldShowCommitsBehindText).toEqual(false); }); }); - it('shouldShowCommitsBehindText', () => { - expect(vm.shouldShowCommitsBehindText).toBeTruthy(); + describe('commitsText', () => { + it('returns singular when there is one commit', () => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 1, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', + targetBranch: 'master', + } }); - vm.mr.divergedCommitsCount = 0; - expect(vm.shouldShowCommitsBehindText).toBeFalsy(); - }); + expect(vm.commitsText).toEqual('1 commit behind'); + }); - it('commitsText', () => { - expect(vm.commitsText).toEqual('commits'); + it('returns plural when there is more than one commit', () => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 2, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>', + targetBranch: 'master', + } }); - vm.mr.divergedCommitsCount = 1; - expect(vm.commitsText).toEqual('commit'); + expect(vm.commitsText).toEqual('2 commits behind'); + }); }); }); describe('template', () => { - let vm; - let el; - const sourceBranchPath = '/foo/bar/mr-widget-refactor'; - const mr = { - divergedCommitsCount: 12, - sourceBranch: 'mr-widget-refactor', - sourceBranchLink: `<a href="${sourceBranchPath}">mr-widget-refactor</a>`, - targetBranchPath: 'foo/bar/commits-path', - targetBranchTreePath: 'foo/bar/tree/path', - targetBranch: 'master', - isOpen: true, - emailPatchesPath: '/mr/email-patches', - plainDiffPath: '/mr/plainDiffPath', - }; - - beforeEach(() => { - vm = createComponent(mr); - el = vm.$el; + describe('common elements', () => { + beforeEach(() => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 12, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>', + sourceBranchRemoved: false, + targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', + targetBranch: 'master', + isOpen: true, + emailPatchesPath: '/mr/email-patches', + plainDiffPath: '/mr/plainDiffPath', + } }); + }); + + it('renders source branch link', () => { + expect( + vm.$el.querySelector('.js-source-branch').innerHTML, + ).toEqual('<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>'); + }); + + it('renders clipboard button', () => { + expect(vm.$el.querySelector('.btn-clipboard')).not.toEqual(null); + }); + + it('renders target branch', () => { + expect(vm.$el.querySelector('.js-target-branch').textContent.trim()).toEqual('master'); + }); + }); + + describe('with an open merge request', () => { + afterEach(() => { + vm.$destroy(); + }); + + beforeEach(() => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 12, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>', + sourceBranchRemoved: false, + targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', + targetBranch: 'master', + isOpen: true, + emailPatchesPath: '/mr/email-patches', + plainDiffPath: '/mr/plainDiffPath', + } }); + }); + + it('renders checkout branch button with modal trigger', () => { + const button = vm.$el.querySelector('.js-check-out-branch'); + + expect(button.textContent.trim()).toEqual('Check out branch'); + expect(button.getAttribute('data-target')).toEqual('#modal_merge_info'); + expect(button.getAttribute('data-toggle')).toEqual('modal'); + }); + + it('renders download dropdown with links', () => { + expect( + vm.$el.querySelector('.js-download-email-patches').textContent.trim(), + ).toEqual('Email patches'); + + expect( + vm.$el.querySelector('.js-download-email-patches').getAttribute('href'), + ).toEqual('/mr/email-patches'); + + expect( + vm.$el.querySelector('.js-download-plain-diff').textContent.trim(), + ).toEqual('Plain diff'); + + expect( + vm.$el.querySelector('.js-download-plain-diff').getAttribute('href'), + ).toEqual('/mr/plainDiffPath'); + }); }); - it('should render template elements correctly', () => { - expect(el.classList.contains('mr-source-target')).toBeTruthy(); - const sourceBranchLink = el.querySelectorAll('.label-branch')[0]; - const targetBranchLink = el.querySelectorAll('.label-branch')[1]; - const commitsCount = el.querySelector('.diverged-commits-count'); - - expect(sourceBranchLink.textContent).toContain(mr.sourceBranch); - expect(targetBranchLink.textContent).toContain(mr.targetBranch); - expect(sourceBranchLink.querySelector('a').getAttribute('href')).toEqual(sourceBranchPath); - expect(targetBranchLink.querySelector('a').getAttribute('href')).toEqual(mr.targetBranchTreePath); - expect(commitsCount.textContent).toContain('12 commits behind'); - expect(commitsCount.querySelector('a').getAttribute('href')).toEqual(mr.targetBranchPath); - - expect(el.textContent).toContain('Check out branch'); - expect(el.querySelectorAll('.dropdown li a')[0].getAttribute('href')).toEqual(mr.emailPatchesPath); - expect(el.querySelectorAll('.dropdown li a')[1].getAttribute('href')).toEqual(mr.plainDiffPath); + describe('with a closed merge request', () => { + beforeEach(() => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 12, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>', + sourceBranchRemoved: false, + targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', + targetBranch: 'master', + isOpen: false, + emailPatchesPath: '/mr/email-patches', + plainDiffPath: '/mr/plainDiffPath', + } }); + }); + + it('does not render checkout branch button with modal trigger', () => { + const button = vm.$el.querySelector('.js-check-out-branch'); + + expect(button).toEqual(null); + }); + + it('does not render download dropdown with links', () => { + expect( + vm.$el.querySelector('.js-download-email-patches'), + ).toEqual(null); + + expect( + vm.$el.querySelector('.js-download-plain-diff'), + ).toEqual(null); + }); }); - it('should not have right action links if the MR state is not open', (done) => { - vm.mr.isOpen = false; - Vue.nextTick(() => { - expect(el.textContent).not.toContain('Check out branch'); - expect(el.querySelectorAll('.dropdown li a').length).toEqual(0); - done(); + describe('without diverged commits', () => { + beforeEach(() => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 0, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>', + sourceBranchRemoved: false, + targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', + targetBranch: 'master', + isOpen: true, + emailPatchesPath: '/mr/email-patches', + plainDiffPath: '/mr/plainDiffPath', + } }); + }); + + it('does not render diverged commits info', () => { + expect(vm.$el.querySelector('.diverged-commits-count')).toEqual(null); }); }); - it('should not render diverged commits count if the MR has no diverged commits', (done) => { - vm.mr.divergedCommitsCount = null; - Vue.nextTick(() => { - expect(el.textContent).not.toContain('commits behind'); - expect(el.querySelectorAll('.diverged-commits-count').length).toEqual(0); - done(); + describe('with diverged commits', () => { + beforeEach(() => { + vm = mountComponent(Component, { mr: { + divergedCommitsCount: 12, + sourceBranch: 'mr-widget-refactor', + sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>', + sourceBranchRemoved: false, + targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', + targetBranch: 'master', + isOpen: true, + emailPatchesPath: '/mr/email-patches', + plainDiffPath: '/mr/plainDiffPath', + } }); + }); + + it('renders diverged commits info', () => { + expect(vm.$el.querySelector('.diverged-commits-count').textContent.trim()).toEqual('(12 commits behind)'); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js index 4da4fc82c26..cc43639f576 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js @@ -1,51 +1,56 @@ import Vue from 'vue'; -import mergeHelpComponent from '~/vue_merge_request_widget/components/mr_widget_merge_help'; - -const props = { - missingBranch: 'this-is-not-the-branch-you-are-looking-for', -}; -const text = `If the ${props.missingBranch} branch exists in your local repository`; - -const createComponent = () => { - const Component = Vue.extend(mergeHelpComponent); - return new Component({ - el: document.createElement('div'), - propsData: props, - }); -}; +import mergeHelpComponent from '~/vue_merge_request_widget/components/mr_widget_merge_help.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('MRWidgetMergeHelp', () => { - describe('props', () => { - it('should have props', () => { - const { missingBranch } = mergeHelpComponent.props; - const MissingBranchTypeClass = missingBranch.type; - - expect(new MissingBranchTypeClass() instanceof String).toBeTruthy(); - expect(missingBranch.required).toBeFalsy(); - expect(missingBranch.default).toEqual(''); - }); + let vm; + let Component; + + beforeEach(() => { + Component = Vue.extend(mergeHelpComponent); }); - describe('template', () => { - let vm; - let el; + afterEach(() => { + vm.$destroy(); + }); + describe('with missing branch', () => { beforeEach(() => { - vm = createComponent(); - el = vm.$el; + vm = mountComponent(Component, { + missingBranch: 'this-is-not-the-branch-you-are-looking-for', + }); }); - it('should have the correct elements', () => { - expect(el.classList.contains('mr-widget-help')).toBeTruthy(); - expect(el.textContent).toContain(text); + it('renders missing branch information', () => { + expect( + vm.$el.textContent.trim().replace(/[\r\n]+/g, ' ').replace(/\s\s+/g, ' '), + ).toEqual( + 'If the this-is-not-the-branch-you-are-looking-for branch exists in your local repository, you can merge this merge request manually using the command line', + ); }); - it('should not show missing branch name if missingBranch props is not provided', (done) => { - vm.missingBranch = null; - Vue.nextTick(() => { - expect(el.textContent).not.toContain(text); - done(); - }); + it('renders button to open help modal', () => { + expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual('#modal_merge_info'); + expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual('modal'); + }); + }); + + describe('without missing branch', () => { + beforeEach(() => { + vm = mountComponent(Component); + }); + + it('renders information about how to merge manually', () => { + expect( + vm.$el.textContent.trim().replace(/[\r\n]+/g, ' ').replace(/\s\s+/g, ' '), + ).toEqual( + 'You can merge this merge request manually using the command line', + ); + }); + + it('renders element to open a modal', () => { + expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual('#modal_merge_info'); + expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual('modal'); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js index f86fb6a0b4b..637bf483deb 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js @@ -1,117 +1,82 @@ import Vue from 'vue'; -import relatedLinksComponent from '~/vue_merge_request_widget/components/mr_widget_related_links'; +import relatedLinksComponent from '~/vue_merge_request_widget/components/mr_widget_related_links.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; -const createComponent = (data) => { - const Component = Vue.extend(relatedLinksComponent); +describe('MRWidgetRelatedLinks', () => { + let vm; - return new Component({ - el: document.createElement('div'), - propsData: data, - }); -}; + const createComponent = (data) => { + const Component = Vue.extend(relatedLinksComponent); -describe('MRWidgetRelatedLinks', () => { - describe('props', () => { - it('should have props', () => { - const { relatedLinks } = relatedLinksComponent.props; + return mountComponent(Component, data); + }; - expect(relatedLinks).toBeDefined(); - expect(relatedLinks.type instanceof Object).toBeTruthy(); - expect(relatedLinks.required).toBeTruthy(); - }); + afterEach(() => { + vm.$destroy(); }); describe('computed', () => { - const data = { - relatedLinks: { - closing: '/foo', - mentioned: '/foo', - assignToMe: '/foo', - }, - }; - - describe('hasLinks', () => { - it('should return correct value when we have links reference', () => { - const vm = createComponent(data); - expect(vm.hasLinks).toBeTruthy(); - - vm.relatedLinks.closing = null; - expect(vm.hasLinks).toBeTruthy(); - - vm.relatedLinks.mentioned = null; - expect(vm.hasLinks).toBeTruthy(); - - vm.relatedLinks.assignToMe = null; - expect(vm.hasLinks).toBeFalsy(); - }); - }); - describe('closesText', () => { - it('returns correct text for open merge request', () => { - data.state = 'open'; - const vm = createComponent(data); + it('returns Closes text for open merge request', () => { + vm = createComponent({ state: 'open', relatedLinks: {} }); expect(vm.closesText).toEqual('Closes'); }); it('returns correct text for closed merge request', () => { - data.state = 'closed'; - const vm = createComponent(data); + vm = createComponent({ state: 'closed', relatedLinks: {} }); expect(vm.closesText).toEqual('Did not close'); }); it('returns correct tense for merged request', () => { - data.state = 'merged'; - const vm = createComponent(data); + vm = createComponent({ state: 'merged', relatedLinks: {} }); expect(vm.closesText).toEqual('Closed'); }); }); }); - describe('template', () => { - it('should have only have closing issues text', () => { - const vm = createComponent({ - relatedLinks: { - closing: '<a href="#">#23</a> and <a>#42</a>', - }, - }); - const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); - - expect(content).toContain('Closes #23 and #42'); - expect(content).not.toContain('Mentions'); + it('should have only have closing issues text', () => { + vm = createComponent({ + relatedLinks: { + closing: '<a href="#">#23</a> and <a>#42</a>', + }, }); + const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); - it('should have only have mentioned issues text', () => { - const vm = createComponent({ - relatedLinks: { - mentioned: '<a href="#">#7</a>', - }, - }); + expect(content).toContain('Closes #23 and #42'); + expect(content).not.toContain('Mentions'); + }); - expect(vm.$el.innerText).toContain('Mentions #7'); - expect(vm.$el.innerText).not.toContain('Closes'); + it('should have only have mentioned issues text', () => { + vm = createComponent({ + relatedLinks: { + mentioned: '<a href="#">#7</a>', + }, }); - it('should have closing and mentioned issues at the same time', () => { - const vm = createComponent({ - relatedLinks: { - closing: '<a href="#">#7</a>', - mentioned: '<a href="#">#23</a> and <a>#42</a>', - }, - }); - const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); + expect(vm.$el.innerText).toContain('Mentions #7'); + expect(vm.$el.innerText).not.toContain('Closes'); + }); - expect(content).toContain('Closes #7'); - expect(content).toContain('Mentions #23 and #42'); + it('should have closing and mentioned issues at the same time', () => { + vm = createComponent({ + relatedLinks: { + closing: '<a href="#">#7</a>', + mentioned: '<a href="#">#23</a> and <a>#42</a>', + }, }); + const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); - it('should have assing issues link', () => { - const vm = createComponent({ - relatedLinks: { - assignToMe: '<a href="#">Assign yourself to these issues</a>', - }, - }); + expect(content).toContain('Closes #7'); + expect(content).toContain('Mentions #23 and #42'); + }); - expect(vm.$el.innerText).toContain('Assign yourself to these issues'); + it('should have assing issues link', () => { + vm = createComponent({ + relatedLinks: { + assignToMe: '<a href="#">Assign yourself to these issues</a>', + }, }); + + expect(vm.$el.innerText).toContain('Assign yourself to these issues'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js new file mode 100644 index 00000000000..c39fcda0071 --- /dev/null +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js @@ -0,0 +1,44 @@ +import Vue from 'vue'; +import mrStatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; + +describe('MR widget status icon component', () => { + let vm; + let Component; + + beforeEach(() => { + Component = Vue.extend(mrStatusIcon); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('while loading', () => { + it('renders loading icon', () => { + vm = mountComponent(Component, { status: 'loading' }); + expect(vm.$el.querySelector('.mr-widget-icon i').classList).toContain('fa-spinner'); + }); + }); + + describe('with status icon', () => { + it('renders ci status icon', () => { + vm = mountComponent(Component, { status: 'failed' }); + expect(vm.$el.querySelector('.js-ci-status-icon-failed')).not.toBeNull(); + }); + }); + + describe('with disabled button', () => { + it('renders a disabled button', () => { + vm = mountComponent(Component, { status: 'failed', showDisabledButton: true }); + expect(vm.$el.querySelector('.js-disabled-merge-button').textContent.trim()).toEqual('Merge'); + }); + }); + + describe('without disabled button', () => { + it('does not render a disabled button', () => { + vm = mountComponent(Component, { status: 'failed' }); + expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeNull(); + }); + }); +}); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js index 4869fb17d96..f98ebdb38e6 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js @@ -1,18 +1,31 @@ import Vue from 'vue'; -import archivedComponent from '~/vue_merge_request_widget/components/states/mr_widget_archived'; +import archivedComponent from '~/vue_merge_request_widget/components/states/mr_widget_archived.vue'; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetArchived', () => { - describe('template', () => { - it('should have correct elements', () => { - const Component = Vue.extend(archivedComponent); - const el = new Component({ - el: document.createElement('div'), - }).$el; + let vm; - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy(); - expect(el.querySelector('button').disabled).toBeTruthy(); - expect(el.innerText).toContain('This project is archived, write access has been disabled'); - }); + beforeEach(() => { + const Component = Vue.extend(archivedComponent); + vm = mountComponent(Component); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders a ci status failed icon', () => { + expect(vm.$el.querySelector('.ci-status-icon')).not.toBeNull(); + }); + + it('renders a disabled button', () => { + expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled'); + expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Merge'); + }); + + it('renders information', () => { + expect( + vm.$el.querySelector('.bold').textContent.trim(), + ).toEqual('This project is archived, write access has been disabled'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js index 6042d7384d5..95c94e95e3a 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js @@ -1,32 +1,47 @@ import Vue from 'vue'; -import autoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed'; - -const mergeError = 'This is the merge error'; +import autoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue'; +import eventHub from '~/vue_merge_request_widget/event_hub'; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetAutoMergeFailed', () => { - describe('props', () => { - it('should have props', () => { - const mrProp = autoMergeFailedComponent.props.mr; + let vm; + const mergeError = 'This is the merge error'; - expect(mrProp.type instanceof Object).toBeTruthy(); - expect(mrProp.required).toBeTruthy(); + beforeEach(() => { + const Component = Vue.extend(autoMergeFailedComponent); + vm = mountComponent(Component, { + mr: { mergeError }, }); }); - describe('template', () => { - const Component = Vue.extend(autoMergeFailedComponent); - const vm = new Component({ - el: document.createElement('div'), - propsData: { - mr: { mergeError }, - }, - }); + afterEach(() => { + vm.$destroy(); + }); + + it('renders failed message', () => { + expect(vm.$el.textContent).toContain('This merge request failed to be merged automatically'); + }); + + it('renders merge error provided', () => { + expect(vm.$el.innerText).toContain(mergeError); + }); + + it('render refresh button', () => { + expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Refresh'); + }); + + it('emits event and shows loading icon when button is clicked', (done) => { + spyOn(eventHub, '$emit'); + vm.$el.querySelector('button').click(); + + expect(eventHub.$emit.calls.argsFor(0)[0]).toEqual('MRWidgetUpdateRequested'); - it('should have correct elements', () => { - expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeFalsy(); - expect(vm.$el.innerText).toContain('This merge request failed to be merged automatically'); - expect(vm.$el.innerText).toContain(mergeError); + Vue.nextTick(() => { + expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled'); + expect( + vm.$el.querySelector('button i').classList, + ).toContain('fa-spinner'); + done(); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js index 6b7aa935ad3..658cadddb81 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js @@ -1,19 +1,29 @@ import Vue from 'vue'; -import checkingComponent from '~/vue_merge_request_widget/components/states/mr_widget_checking'; +import checkingComponent from '~/vue_merge_request_widget/components/states/mr_widget_checking.vue'; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetChecking', () => { - describe('template', () => { - it('should have correct elements', () => { - const Component = Vue.extend(checkingComponent); - const el = new Component({ - el: document.createElement('div'), - }).$el; + let Component; + let vm; - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy(); - expect(el.querySelector('button').disabled).toBeTruthy(); - expect(el.innerText).toContain('Checking ability to merge automatically'); - expect(el.querySelector('i')).toBeDefined(); - }); + beforeEach(() => { + Component = Vue.extend(checkingComponent); + vm = mountComponent(Component); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders disabled button', () => { + expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled'); + }); + + it('renders loading icon', () => { + expect(vm.$el.querySelector('.mr-widget-icon i').classList).toContain('fa-spinner'); + }); + + it('renders information about merging', () => { + expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual('Checking ability to merge automatically'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js index 1bf97bbf093..51a34739ee9 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js @@ -1,74 +1,58 @@ import Vue from 'vue'; -import closedComponent from '~/vue_merge_request_widget/components/states/mr_widget_closed'; - -const mr = { - targetBranch: 'good-branch', - targetBranchPath: '/good-branch', - metrics: { - mergedBy: {}, - mergedAt: 'mergedUpdatedAt', - closedBy: { - name: 'Fatih Acet', - username: 'fatihacet', - }, - closedAt: 'closedEventUpdatedAt', - readableMergedAt: '', - readableClosedAt: '', - }, - updatedAt: 'mrUpdatedAt', - closedAt: '1 day ago', -}; - -const createComponent = () => { - const Component = Vue.extend(closedComponent); - - return new Component({ - el: document.createElement('div'), - propsData: { mr }, - }); -}; +import closedComponent from '~/vue_merge_request_widget/components/states/mr_widget_closed.vue'; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetClosed', () => { - describe('props', () => { - it('should have props', () => { - const mrProp = closedComponent.props.mr; - - expect(mrProp.type instanceof Object).toBeTruthy(); - expect(mrProp.required).toBeTruthy(); - }); + let vm; + + beforeEach(() => { + const Component = Vue.extend(closedComponent); + vm = mountComponent(Component, { mr: { + metrics: { + mergedBy: {}, + closedBy: { + name: 'Administrator', + username: 'root', + webUrl: 'http://localhost:3000/root', + avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + }, + mergedAt: 'Jan 24, 2018 1:02pm GMT+0000', + closedAt: 'Jan 24, 2018 1:02pm GMT+0000', + readableMergedAt: '', + readableClosedAt: 'less than a minute ago', + }, + targetBranchPath: '/twitter/flight/commits/so_long_jquery', + targetBranch: 'so_long_jquery', + } }); }); - describe('components', () => { - it('should have components added', () => { - expect(closedComponent.components['mr-widget-author-and-time']).toBeDefined(); - }); + afterEach(() => { + vm.$destroy(); }); - describe('template', () => { - let vm; - let el; + it('renders warning icon', () => { + expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull(); + }); - beforeEach(() => { - vm = createComponent(); - el = vm.$el; - }); + it('renders closed by information with author and time', () => { + expect( + vm.$el.querySelector('.js-mr-widget-author').textContent.trim().replace(/\s\s+/g, ' '), + ).toContain( + 'Closed by Administrator less than a minute ago', + ); + }); - afterEach(() => { - vm.$destroy(); - }); + it('links to the user that closed the MR', () => { + expect(vm.$el.querySelector('.author-link').getAttribute('href')).toEqual('http://localhost:3000/root'); + }); - it('should have correct elements', () => { - expect(el.querySelector('h4').textContent).toContain('Closed by'); - expect(el.querySelector('h4').textContent).toContain(mr.metrics.closedBy.name); - expect(el.textContent).toContain('The changes were not merged into'); - expect(el.querySelector('.label-branch').getAttribute('href')).toEqual(mr.targetBranchPath); - expect(el.querySelector('.label-branch').textContent).toContain(mr.targetBranch); - }); + it('renders information about the changes not being merged', () => { + expect( + vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' '), + ).toContain('The changes were not merged into so_long_jquery'); + }); - it('should use closedEvent updatedAt as tooltip title', () => { - expect( - el.querySelector('time').getAttribute('title'), - ).toBe('closedEventUpdatedAt'); - }); + it('renders link for target branch', () => { + expect(vm.$el.querySelector('.label-branch').getAttribute('href')).toEqual('/twitter/flight/commits/so_long_jquery'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js index 5d4c7ec09dc..a7d69fdcdb9 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js @@ -1,105 +1,85 @@ import Vue from 'vue'; -import conflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts'; +import conflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue'; import mountComponent from '../../../helpers/vue_mount_component_helper'; -const ConflictsComponent = Vue.extend(conflictsComponent); -const path = '/conflicts'; - describe('MRWidgetConflicts', () => { - describe('props', () => { - it('should have props', () => { - const { mr } = conflictsComponent.props; + let Component; + let vm; + const path = '/conflicts'; - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - }); + beforeEach(() => { + Component = Vue.extend(conflictsComponent); }); - describe('template', () => { - describe('when allowed to merge', () => { - let vm; - - beforeEach(() => { - vm = mountComponent(ConflictsComponent, { - mr: { - canMerge: true, - conflictResolutionPath: path, - }, - }); - }); - - afterEach(() => { - vm.$destroy(); - }); - - it('should tell you about conflicts without bothering other people', () => { - expect(vm.$el.textContent).toContain('There are merge conflicts'); - expect(vm.$el.textContent).not.toContain('ask someone with write access'); - }); - - it('should allow you to resolve the conflicts', () => { - const resolveButton = vm.$el.querySelector('.js-resolve-conflicts-button'); + afterEach(() => { + vm.$destroy(); + }); - expect(resolveButton.textContent).toContain('Resolve conflicts'); - expect(resolveButton.getAttribute('href')).toEqual(path); + describe('when allowed to merge', () => { + beforeEach(() => { + vm = mountComponent(Component, { + mr: { + canMerge: true, + conflictResolutionPath: path, + }, }); + }); - it('should have merge buttons', () => { - const mergeButton = vm.$el.querySelector('.js-disabled-merge-button'); - const mergeLocallyButton = vm.$el.querySelector('.js-merge-locally-button'); - - expect(mergeButton.textContent).toContain('Merge'); - expect(mergeButton.disabled).toBeTruthy(); - expect(mergeButton.classList.contains('btn-success')).toEqual(true); - expect(mergeLocallyButton.textContent).toContain('Merge locally'); - }); + it('should tell you about conflicts without bothering other people', () => { + expect(vm.$el.textContent).toContain('There are merge conflicts'); + expect(vm.$el.textContent).not.toContain('ask someone with write access'); }); - describe('when user does not have permission to merge', () => { - let vm; + it('should allow you to resolve the conflicts', () => { + const resolveButton = vm.$el.querySelector('.js-resolve-conflicts-button'); - beforeEach(() => { - vm = mountComponent(ConflictsComponent, { - mr: { - canMerge: false, - }, - }); - }); + expect(resolveButton.textContent).toContain('Resolve conflicts'); + expect(resolveButton.getAttribute('href')).toEqual(path); + }); - afterEach(() => { - vm.$destroy(); - }); + it('should have merge buttons', () => { + const mergeButton = vm.$el.querySelector('.js-disabled-merge-button'); + const mergeLocallyButton = vm.$el.querySelector('.js-merge-locally-button'); - it('should show proper message', () => { - expect(vm.$el.textContent).toContain('ask someone with write access'); - }); + expect(mergeButton.textContent).toContain('Merge'); + expect(mergeButton.disabled).toBeTruthy(); + expect(mergeButton.classList.contains('btn-success')).toEqual(true); + expect(mergeLocallyButton.textContent).toContain('Merge locally'); + }); + }); - it('should not have action buttons', () => { - expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeDefined(); - expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toBeNull(); - expect(vm.$el.querySelector('.js-merge-locally-button')).toBeNull(); + describe('when user does not have permission to merge', () => { + beforeEach(() => { + vm = mountComponent(Component, { + mr: { + canMerge: false, + }, }); }); - describe('when fast-forward or semi-linear merge enabled', () => { - let vm; + it('should show proper message', () => { + expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain('ask someone with write access'); + }); - beforeEach(() => { - vm = mountComponent(ConflictsComponent, { - mr: { - shouldBeRebased: true, - }, - }); - }); + it('should not have action buttons', () => { + expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeDefined(); + expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toBeNull(); + expect(vm.$el.querySelector('.js-merge-locally-button')).toBeNull(); + }); + }); - afterEach(() => { - vm.$destroy(); + describe('when fast-forward or semi-linear merge enabled', () => { + beforeEach(() => { + vm = mountComponent(Component, { + mr: { + shouldBeRebased: true, + }, }); + }); - it('should tell you to rebase locally', () => { - expect(vm.$el.textContent).toContain('Fast-forward merge is not possible.'); - expect(vm.$el.textContent).toContain('To merge this request, first rebase locally'); - }); + it('should tell you to rebase locally', () => { + expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain('Fast-forward merge is not possible.'); + expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain('To merge this request, first rebase locally'); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js index cef365eec8a..a57b9811e08 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js @@ -1,45 +1,37 @@ import Vue from 'vue'; -import failedToMergeComponent from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge'; +import failedToMergeComponent from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue'; import eventHub from '~/vue_merge_request_widget/event_hub'; - -const mr = { - mergeError: 'Merge error happened.', -}; -const createComponent = () => { - const Component = Vue.extend(failedToMergeComponent); - return new Component({ - el: document.createElement('div'), - propsData: { mr }, - }); -}; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetFailedToMerge', () => { - describe('data', () => { - it('should have default data', () => { - const data = failedToMergeComponent.data(); + let Component; + let vm; + + beforeEach(() => { + Component = Vue.extend(failedToMergeComponent); + spyOn(eventHub, '$emit'); + vm = mountComponent(Component, { mr: { + mergeError: 'Merge error happened.', + } }); + }); - expect(data.timer).toEqual(10); - expect(data.isRefreshing).toBeFalsy(); - }); + afterEach(() => { + vm.$destroy(); }); describe('computed', () => { describe('timerText', () => { it('should return correct timer text', () => { - const vm = createComponent(); - expect(vm.timerText).toEqual('10 seconds'); + expect(vm.timerText).toEqual('Refreshing in 10 seconds to show the updated status...'); vm.timer = 1; - expect(vm.timerText).toEqual('a second'); + expect(vm.timerText).toEqual('Refreshing in a second to show the updated status...'); }); }); }); describe('created', () => { it('should disable polling', () => { - spyOn(eventHub, '$emit'); - createComponent(); - expect(eventHub.$emit).toHaveBeenCalledWith('DisablePolling'); }); }); @@ -47,13 +39,10 @@ describe('MRWidgetFailedToMerge', () => { describe('methods', () => { describe('refresh', () => { it('should emit event to request component refresh', () => { - spyOn(eventHub, '$emit'); - const vm = createComponent(); - - expect(vm.isRefreshing).toBeFalsy(); + expect(vm.isRefreshing).toEqual(false); vm.refresh(); - expect(vm.isRefreshing).toBeTruthy(); + expect(vm.isRefreshing).toEqual(true); expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested'); expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling'); }); @@ -61,12 +50,11 @@ describe('MRWidgetFailedToMerge', () => { describe('updateTimer', () => { it('should update timer and emit event when timer end', () => { - const vm = createComponent(); spyOn(vm, 'refresh'); expect(vm.timer).toEqual(10); - for (let i = 0; i < 10; i++) { // eslint-disable-line + for (let i = 0; i < 10; i += 1) { expect(vm.timer).toEqual(10 - i); vm.updateTimer(); } @@ -76,47 +64,54 @@ describe('MRWidgetFailedToMerge', () => { }); }); - describe('template', () => { - let vm; - let el; + describe('while it is refreshing', () => { + it('renders Refresing now', (done) => { + vm.isRefreshing = true; - beforeEach(() => { - vm = createComponent(); - el = vm.$el; + Vue.nextTick(() => { + expect(vm.$el.querySelector('.js-refresh-label').textContent.trim()).toEqual('Refreshing now'); + done(); + }); }); + }); - it('should have correct elements', (done) => { - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.innerText).toContain('Merge error happened.'); - expect(el.innerText).toContain('Refreshing in 10 seconds'); - expect(el.innerText).not.toContain('Merge failed.'); - expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy(); - expect(el.querySelector('button').innerText).toContain('Merge'); - expect(el.querySelector('.js-refresh-button').innerText).toContain('Refresh now'); - expect(el.querySelector('.js-refresh-label')).toEqual(null); - expect(el.innerText).not.toContain('Refreshing now'); - setTimeout(() => { - expect(el.innerText).toContain('Refreshing in 9 seconds'); - done(); - }, 1010); + describe('while it is not regresing', () => { + it('renders warning icon and disabled merge button', () => { + expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull(); + expect(vm.$el.querySelector('.js-disabled-merge-button').getAttribute('disabled')).toEqual('disabled'); + }); + + it('renders given error', () => { + expect(vm.$el.querySelector('.has-error-message').textContent.trim()).toEqual('Merge error happened..'); }); - it('should just generic merge failed message if merge_error is not available', (done) => { - vm.mr.mergeError = null; + it('renders refresh button', () => { + expect(vm.$el.querySelector('.js-refresh-button').textContent.trim()).toEqual('Refresh now'); + }); - Vue.nextTick(() => { - expect(el.innerText).toContain('Merge failed.'); - expect(el.innerText).not.toContain('Merge error happened.'); - done(); - }); + it('renders remaining time', () => { + expect( + vm.$el.querySelector('.has-custom-error').textContent.trim(), + ).toEqual('Refreshing in 10 seconds to show the updated status...'); + }); + }); + + it('should just generic merge failed message if merge_error is not available', (done) => { + vm.mr.mergeError = null; + + Vue.nextTick(() => { + expect(vm.$el.innerText).toContain('Merge failed.'); + expect(vm.$el.innerText).not.toContain('Merge error happened.'); + done(); }); + }); - it('should show refresh label when refresh requested', () => { - vm.refresh(); - Vue.nextTick(() => { - expect(el.innerText).not.toContain('Merge failed. Refreshing'); - expect(el.innerText).toContain('Refreshing now'); - }); + it('should show refresh label when refresh requested', (done) => { + vm.refresh(); + Vue.nextTick(() => { + expect(vm.$el.innerText).not.toContain('Merge failed. Refreshing'); + expect(vm.$el.innerText).toContain('Refreshing now'); + done(); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_locked_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_locked_spec.js deleted file mode 100644 index 237035648cf..00000000000 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_locked_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import Vue from 'vue'; -import mergingComponent from '~/vue_merge_request_widget/components/states/mr_widget_merging'; - -describe('MRWidgetMerging', () => { - describe('props', () => { - it('should have props', () => { - const { mr } = mergingComponent.props; - - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - }); - }); - - describe('template', () => { - it('should have correct elements', () => { - const Component = Vue.extend(mergingComponent); - const mr = { - targetBranchPath: '/branch-path', - targetBranch: 'branch', - }; - const el = new Component({ - el: document.createElement('div'), - propsData: { mr }, - }).$el; - - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.innerText).toContain('This merge request is in the process of being merged'); - expect(el.innerText).toContain('changes will be merged into'); - expect(el.querySelector('.label-branch a').getAttribute('href')).toEqual(mr.targetBranchPath); - expect(el.querySelector('.label-branch a').textContent).toContain(mr.targetBranch); - }); - }); -}); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js index 5f4df15bcd6..df56c4e2c5c 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js @@ -1,77 +1,50 @@ import Vue from 'vue'; -import mwpsComponent from '~/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds'; +import mwpsComponent from '~/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue'; import eventHub from '~/vue_merge_request_widget/event_hub'; - -const targetBranchPath = '/foo/bar'; -const targetBranch = 'foo'; -const sha = '1EA2EZ34'; - -const createComponent = () => { - const Component = Vue.extend(mwpsComponent); - const mr = { - shouldRemoveSourceBranch: false, - canRemoveSourceBranch: true, - canCancelAutomaticMerge: true, - mergeUserId: 1, - currentUserId: 1, - setToMWPSBy: {}, - sha, - targetBranchPath, - targetBranch, - }; - - const service = { - cancelAutomaticMerge() {}, - mergeResource: { - save() {}, - }, - }; - - return new Component({ - el: document.createElement('div'), - propsData: { mr, service }, - }); -}; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetMergeWhenPipelineSucceeds', () => { - describe('props', () => { - it('should have props', () => { - const { mr, service } = mwpsComponent.props; - - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - - expect(service.type instanceof Object).toBeTruthy(); - expect(service.required).toBeTruthy(); + let vm; + const targetBranchPath = '/foo/bar'; + const targetBranch = 'foo'; + const sha = '1EA2EZ34'; + + beforeEach(() => { + const Component = Vue.extend(mwpsComponent); + spyOn(eventHub, '$emit'); + + vm = mountComponent(Component, { + mr: { + shouldRemoveSourceBranch: false, + canRemoveSourceBranch: true, + canCancelAutomaticMerge: true, + mergeUserId: 1, + currentUserId: 1, + setToMWPSBy: {}, + sha, + targetBranchPath, + targetBranch, + }, + service: { + cancelAutomaticMerge() {}, + mergeResource: { + save() {}, + }, + }, }); }); - describe('components', () => { - it('should have components added', () => { - expect(mwpsComponent.components['mr-widget-author']).toBeDefined(); - }); - }); - - describe('data', () => { - it('should have default data', () => { - const data = mwpsComponent.data(); - - expect(data.isCancellingAutoMerge).toBeFalsy(); - expect(data.isRemovingSourceBranch).toBeFalsy(); - }); + afterEach(() => { + vm.$destroy(); }); describe('computed', () => { describe('canRemoveSourceBranch', () => { it('should return true when user is able to remove source branch', () => { - const vm = createComponent(); - expect(vm.canRemoveSourceBranch).toBeTruthy(); }); it('should return false when user id is not the same with who set the MWPS', () => { - const vm = createComponent(); - vm.mr.mergeUserId = 2; expect(vm.canRemoveSourceBranch).toBeFalsy(); @@ -83,15 +56,11 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { }); it('should return false when shouldRemoveSourceBranch set to false', () => { - const vm = createComponent(); - vm.mr.shouldRemoveSourceBranch = true; expect(vm.canRemoveSourceBranch).toBeFalsy(); }); it('should return false if user is not able to remove the source branch', () => { - const vm = createComponent(); - vm.mr.canRemoveSourceBranch = false; expect(vm.canRemoveSourceBranch).toBeFalsy(); }); @@ -101,11 +70,9 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { describe('methods', () => { describe('cancelAutomaticMerge', () => { it('should set flag and call service then tell main component to update the widget with data', (done) => { - const vm = createComponent(); const mrObj = { is_new_mr_data: true, }; - spyOn(eventHub, '$emit'); spyOn(vm.service, 'cancelAutomaticMerge').and.returnValue(new Promise((resolve) => { resolve({ data: mrObj, @@ -123,8 +90,6 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { describe('removeSourceBranch', () => { it('should set flag and call service then request main component to update the widget', (done) => { - const vm = createComponent(); - spyOn(eventHub, '$emit'); spyOn(vm.service.mergeResource, 'save').and.returnValue(new Promise((resolve) => { resolve({ data: { @@ -148,31 +113,23 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { }); describe('template', () => { - let vm; - let el; - - beforeEach(() => { - vm = createComponent(); - el = vm.$el; - }); - it('should have correct elements', () => { - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.innerText).toContain('to be merged automatically when the pipeline succeeds'); - expect(el.innerText).toContain('The changes will be merged into'); - expect(el.innerText).toContain(targetBranch); - expect(el.innerText).toContain('The source branch will not be removed'); - expect(el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge'); - expect(el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy(); - expect(el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch'); - expect(el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy(); + expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); + expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds'); + expect(vm.$el.innerText).toContain('The changes will be merged into'); + expect(vm.$el.innerText).toContain(targetBranch); + expect(vm.$el.innerText).toContain('The source branch will not be removed'); + expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge'); + expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy(); + expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch'); + expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy(); }); it('should disable cancel auto merge button when the action is in progress', (done) => { vm.isCancellingAutoMerge = true; Vue.nextTick(() => { - expect(el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeTruthy(); + expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeTruthy(); done(); }); }); @@ -181,7 +138,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { vm.mr.shouldRemoveSourceBranch = true; Vue.nextTick(() => { - const normalizedText = el.innerText.replace(/\s+/g, ' '); + const normalizedText = vm.$el.innerText.replace(/\s+/g, ' '); expect(normalizedText).toContain('The source branch will be removed'); expect(normalizedText).not.toContain('The source branch will not be removed'); done(); @@ -192,7 +149,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { vm.mr.currentUserId = 4; Vue.nextTick(() => { - expect(el.querySelector('.js-remove-source-branch')).toEqual(null); + expect(vm.$el.querySelector('.js-remove-source-branch')).toEqual(null); done(); }); }); @@ -201,7 +158,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { vm.isRemovingSourceBranch = true; Vue.nextTick(() => { - expect(el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeTruthy(); + expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeTruthy(); done(); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js index 2dc3b72ea40..43a989393ba 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -1,108 +1,99 @@ import Vue from 'vue'; -import mergedComponent from '~/vue_merge_request_widget/components/states/mr_widget_merged'; +import mergedComponent from '~/vue_merge_request_widget/components/states/mr_widget_merged.vue'; import eventHub from '~/vue_merge_request_widget/event_hub'; - -const targetBranch = 'foo'; - -const createComponent = () => { - const Component = Vue.extend(mergedComponent); - const mr = { - isRemovingSourceBranch: false, - cherryPickInForkPath: false, - canCherryPickInCurrentMR: true, - revertInForkPath: false, - canRevertInCurrentMR: true, - canRemoveSourceBranch: true, - sourceBranchRemoved: true, - metrics: { - mergedBy: {}, - mergedAt: 'mergedUpdatedAt', - readableMergedAt: '', - closedBy: {}, - closedAt: 'mergedUpdatedAt', - readableClosedAt: '', - }, - updatedAt: 'mrUpdatedAt', - targetBranch, - }; - - const service = { - removeSourceBranch() {}, - }; - - return new Component({ - el: document.createElement('div'), - propsData: { mr, service }, - }); -}; +import mountComponent from '../../../helpers/vue_mount_component_helper'; describe('MRWidgetMerged', () => { - describe('props', () => { - it('should have props', () => { - const { mr, service } = mergedComponent.props; - - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - - expect(service.type instanceof Object).toBeTruthy(); - expect(service.required).toBeTruthy(); - }); - }); - - describe('components', () => { - it('should have components added', () => { - expect(mergedComponent.components['mr-widget-author-and-time']).toBeDefined(); - }); + let vm; + const targetBranch = 'foo'; + + beforeEach(() => { + const Component = Vue.extend(mergedComponent); + const mr = { + isRemovingSourceBranch: false, + cherryPickInForkPath: false, + canCherryPickInCurrentMR: true, + revertInForkPath: false, + canRevertInCurrentMR: true, + canRemoveSourceBranch: true, + sourceBranchRemoved: true, + metrics: { + mergedBy: { + name: 'Administrator', + username: 'root', + webUrl: 'http://localhost:3000/root', + avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + }, + mergedAt: 'Jan 24, 2018 1:02pm GMT+0000', + readableMergedAt: '', + closedBy: {}, + closedAt: 'Jan 24, 2018 1:02pm GMT+0000', + readableClosedAt: '', + }, + updatedAt: 'mergedUpdatedAt', + targetBranch, + }; + + const service = { + removeSourceBranch() {}, + }; + + spyOn(eventHub, '$emit'); + + vm = mountComponent(Component, { mr, service }); }); - describe('data', () => { - it('should have default data', () => { - const data = mergedComponent.data(); - - expect(data.isMakingRequest).toBeFalsy(); - }); + afterEach(() => { + vm.$destroy(); }); describe('computed', () => { describe('shouldShowRemoveSourceBranch', () => { - it('should correct value when fields changed', () => { - const vm = createComponent(); + it('returns true when sourceBranchRemoved is false', () => { vm.mr.sourceBranchRemoved = false; - expect(vm.shouldShowRemoveSourceBranch).toBeTruthy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(true); + }); + it('returns false wehn sourceBranchRemoved is true', () => { vm.mr.sourceBranchRemoved = true; - expect(vm.shouldShowRemoveSourceBranch).toBeFalsy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(false); + }); + it('returns false when canRemoveSourceBranch is false', () => { vm.mr.sourceBranchRemoved = false; vm.mr.canRemoveSourceBranch = false; - expect(vm.shouldShowRemoveSourceBranch).toBeFalsy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(false); + }); + it('returns false when is making request', () => { vm.mr.canRemoveSourceBranch = true; vm.isMakingRequest = true; - expect(vm.shouldShowRemoveSourceBranch).toBeFalsy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(false); + }); + it('returns true when all are true', () => { vm.mr.isRemovingSourceBranch = true; vm.mr.canRemoveSourceBranch = true; vm.isMakingRequest = true; - expect(vm.shouldShowRemoveSourceBranch).toBeFalsy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(false); }); }); + describe('shouldShowSourceBranchRemoving', () => { it('should correct value when fields changed', () => { - const vm = createComponent(); vm.mr.sourceBranchRemoved = false; - expect(vm.shouldShowSourceBranchRemoving).toBeFalsy(); + expect(vm.shouldShowSourceBranchRemoving).toEqual(false); vm.mr.sourceBranchRemoved = true; - expect(vm.shouldShowRemoveSourceBranch).toBeFalsy(); + expect(vm.shouldShowRemoveSourceBranch).toEqual(false); vm.mr.sourceBranchRemoved = false; vm.isMakingRequest = true; - expect(vm.shouldShowSourceBranchRemoving).toBeTruthy(); + expect(vm.shouldShowSourceBranchRemoving).toEqual(true); vm.isMakingRequest = false; vm.mr.isRemovingSourceBranch = true; - expect(vm.shouldShowSourceBranchRemoving).toBeTruthy(); + expect(vm.shouldShowSourceBranchRemoving).toEqual(true); }); }); }); @@ -110,8 +101,6 @@ describe('MRWidgetMerged', () => { describe('methods', () => { describe('removeSourceBranch', () => { it('should set flag and call service then request main component to update the widget', (done) => { - const vm = createComponent(); - spyOn(eventHub, '$emit'); spyOn(vm.service, 'removeSourceBranch').and.returnValue(new Promise((resolve) => { resolve({ data: { @@ -123,7 +112,7 @@ describe('MRWidgetMerged', () => { vm.removeSourceBranch(); setTimeout(() => { const args = eventHub.$emit.calls.argsFor(0); - expect(vm.isMakingRequest).toBeTruthy(); + expect(vm.isMakingRequest).toEqual(true); expect(args[0]).toEqual('MRWidgetUpdateRequested'); expect(args[1]).not.toThrow(); done(); @@ -132,53 +121,50 @@ describe('MRWidgetMerged', () => { }); }); - describe('template', () => { - let vm; - let el; + it('has merged by information', () => { + expect(vm.$el.textContent).toContain('Merged by'); + expect(vm.$el.textContent).toContain('Administrator'); + }); - beforeEach(() => { - vm = createComponent(); - el = vm.$el; - }); + it('renders branch information', () => { + expect(vm.$el.textContent).toContain('The changes were merged into'); + expect(vm.$el.textContent).toContain(targetBranch); + }); - it('should have correct elements', () => { - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.querySelector('.js-mr-widget-author')).toBeDefined(); - expect(el.innerText).toContain('The changes were merged into'); - expect(el.innerText).toContain(targetBranch); - expect(el.innerText).toContain('The source branch has been removed'); - expect(el.innerText).toContain('Revert'); - expect(el.innerText).toContain('Cherry-pick'); - expect(el.innerText).not.toContain('You can remove source branch now'); - expect(el.innerText).not.toContain('The source branch is being removed'); - }); + it('renders information about branch being removed', () => { + expect(vm.$el.textContent).toContain('The source branch has been removed'); + }); - it('should not show source branch removed text', (done) => { - vm.mr.sourceBranchRemoved = false; + it('shows revert and cherry-pick buttons', () => { + expect(vm.$el.textContent).toContain('Revert'); + expect(vm.$el.textContent).toContain('Cherry-pick'); + }); - Vue.nextTick(() => { - expect(el.innerText).toContain('You can remove source branch now'); - expect(el.innerText).not.toContain('The source branch has been removed'); - done(); - }); + it('should not show source branch removed text', (done) => { + vm.mr.sourceBranchRemoved = false; + + Vue.nextTick(() => { + expect(vm.$el.innerText).toContain('You can remove source branch now'); + expect(vm.$el.innerText).not.toContain('The source branch has been removed'); + done(); }); + }); - it('should show source branch removing text', (done) => { - vm.mr.isRemovingSourceBranch = true; - vm.mr.sourceBranchRemoved = false; + it('should show source branch removing text', (done) => { + vm.mr.isRemovingSourceBranch = true; + vm.mr.sourceBranchRemoved = false; - Vue.nextTick(() => { - expect(el.innerText).toContain('The source branch is being removed'); - expect(el.innerText).not.toContain('You can remove source branch now'); - expect(el.innerText).not.toContain('The source branch has been removed'); - done(); - }); + Vue.nextTick(() => { + expect(vm.$el.innerText).toContain('The source branch is being removed'); + expect(vm.$el.innerText).not.toContain('You can remove source branch now'); + expect(vm.$el.innerText).not.toContain('The source branch has been removed'); + done(); }); + }); - it('should use mergedEvent updatedAt as tooltip title', () => { - expect( - el.querySelector('time').getAttribute('title'), - ).toBe('mergedUpdatedAt'); - }); + it('should use mergedEvent mergedAt as tooltip title', () => { + expect( + vm.$el.querySelector('time').getAttribute('title'), + ).toBe('Jan 24, 2018 1:02pm GMT+0000'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js new file mode 100644 index 00000000000..0b2ed2d4086 --- /dev/null +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js @@ -0,0 +1,34 @@ +import Vue from 'vue'; +import mergingComponent from '~/vue_merge_request_widget/components/states/mr_widget_merging.vue'; +import mountComponent from '../../../helpers/vue_mount_component_helper'; + +describe('MRWidgetMerging', () => { + let vm; + beforeEach(() => { + const Component = Vue.extend(mergingComponent); + + vm = mountComponent(Component, { mr: { + targetBranchPath: '/branch-path', + targetBranch: 'branch', + } }); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders information about merge request being merged', () => { + expect( + vm.$el.querySelector('.media-body').textContent.trim().replace(/\s\s+/g, ' ').replace(/[\r\n]+/g, ' '), + ).toContain('This merge request is in the process of being merged'); + }); + + it('renders branch information', () => { + expect( + vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' ').replace(/[\r\n]+/g, ' '), + ).toEqual('The changes will be merged into branch'); + expect( + vm.$el.querySelector('a').getAttribute('href'), + ).toEqual('/branch-path'); + }); +}); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js index 1127576617b..073f26cc78f 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -170,14 +170,14 @@ describe('MRWidgetReadyToMerge', () => { expect(vm.iconClass).toEqual('success'); }); - it('shows x for failed status', () => { + it('shows warning icon for failed status', () => { vm.mr.hasCI = true; - expect(vm.iconClass).toEqual('failed'); + expect(vm.iconClass).toEqual('warning'); }); - it('shows x for merge not allowed', () => { + it('shows warning icon for merge not allowed', () => { vm.mr.hasCI = true; - expect(vm.iconClass).toEqual('failed'); + expect(vm.iconClass).toEqual('warning'); }); }); @@ -371,6 +371,10 @@ describe('MRWidgetReadyToMerge', () => { }); }); + beforeEach(() => { + loadFixtures('merge_requests/merge_request_of_current_user.html.raw'); + }); + it('should call start and stop polling when MR merged', (done) => { spyOn(eventHub, '$emit'); spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged')); @@ -392,6 +396,47 @@ describe('MRWidgetReadyToMerge', () => { }, 333); }); + it('updates status box', (done) => { + spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged')); + spyOn(vm, 'initiateRemoveSourceBranchPolling'); + + vm.handleMergePolling(() => {}, () => {}); + + setTimeout(() => { + const statusBox = document.querySelector('.status-box'); + expect(statusBox.classList.contains('status-box-mr-merged')).toBeTruthy(); + expect(statusBox.textContent).toContain('Merged'); + + done(); + }); + }); + + it('hides close button', (done) => { + spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged')); + spyOn(vm, 'initiateRemoveSourceBranchPolling'); + + vm.handleMergePolling(() => {}, () => {}); + + setTimeout(() => { + expect(document.querySelector('.btn-close').classList.contains('hidden')).toBeTruthy(); + + done(); + }); + }); + + it('updates merge request count badge', (done) => { + spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged')); + spyOn(vm, 'initiateRemoveSourceBranchPolling'); + + vm.handleMergePolling(() => {}, () => {}); + + setTimeout(() => { + expect(document.querySelector('.js-merge-counter').textContent).toBe('0'); + + done(); + }); + }); + it('should continue polling until MR is merged', (done) => { spyOn(vm.service, 'poll').and.returnValue(returnPromise('some_other_state')); spyOn(vm, 'initiateRemoveSourceBranchPolling'); diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js index ca29c9fee32..3dd75307484 100644 --- a/spec/javascripts/vue_mr_widget/mock_data.js +++ b/spec/javascripts/vue_mr_widget/mock_data.js @@ -14,7 +14,6 @@ export default { "updated_by_id": null, "created_at": "2017-04-07T12:27:26.718Z", "updated_at": "2017-04-07T15:39:25.852Z", - "deleted_at": null, "time_estimate": 0, "total_time_spent": 0, "human_time_estimate": null, @@ -39,7 +38,7 @@ export default { "username": "root", "id": 1, "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "merged_at": "2017-04-07T15:39:25.696Z", @@ -51,7 +50,7 @@ export default { "username": "root", "id": 1, "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "merge_user": null, @@ -65,7 +64,7 @@ export default { "username": "root", "id": 1, "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, "active": false, @@ -160,10 +159,10 @@ export default { "username": "root", "id": 1, "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" }, - "author_gravatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "author_gravatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "commit_url": "http://localhost:3000/root/acets-app/commit/104096c51715e12e7ae41f9333e9fa35b73f385d", "commit_path": "/root/acets-app/commit/104096c51715e12e7ae41f9333e9fa35b73f385d" }, |