diff options
Diffstat (limited to 'spec/javascripts/vue_shared/components')
4 files changed, 434 insertions, 0 deletions
diff --git a/spec/javascripts/vue_shared/components/commit_spec.js b/spec/javascripts/vue_shared/components/commit_spec.js new file mode 100644 index 00000000000..df547299d75 --- /dev/null +++ b/spec/javascripts/vue_shared/components/commit_spec.js @@ -0,0 +1,130 @@ +import Vue from 'vue'; +import commitComp from '~/vue_shared/components/commit'; + +describe('Commit component', () => { + let props; + let component; + let CommitComponent; + + beforeEach(() => { + CommitComponent = Vue.extend(commitComp); + }); + + it('should render a code-fork icon if it does not represent a tag', () => { + component = new CommitComponent({ + propsData: { + tag: false, + commitRef: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commitUrl: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + shortSha: 'b7836edd', + title: 'Commit message', + author: { + avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', + web_url: 'https://gitlab.com/jschatz1', + username: 'jschatz1', + }, + }, + }).$mount(); + + expect(component.$el.querySelector('.icon-container i').classList).toContain('fa-code-fork'); + }); + + describe('Given all the props', () => { + beforeEach(() => { + props = { + tag: true, + commitRef: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commitUrl: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + shortSha: 'b7836edd', + title: 'Commit message', + author: { + avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', + web_url: 'https://gitlab.com/jschatz1', + username: 'jschatz1', + }, + commitIconSvg: '<svg></svg>', + }; + + component = new CommitComponent({ + propsData: props, + }).$mount(); + }); + + it('should render a tag icon if it represents a tag', () => { + expect(component.$el.querySelector('.icon-container i').classList).toContain('fa-tag'); + }); + + it('should render a link to the ref url', () => { + expect(component.$el.querySelector('.branch-name').getAttribute('href')).toEqual(props.commitRef.ref_url); + }); + + it('should render the ref name', () => { + expect(component.$el.querySelector('.branch-name').textContent).toContain(props.commitRef.name); + }); + + it('should render the commit short sha with a link to the commit url', () => { + expect(component.$el.querySelector('.commit-id').getAttribute('href')).toEqual(props.commitUrl); + expect(component.$el.querySelector('.commit-id').textContent).toContain(props.shortSha); + }); + + it('should render the given commitIconSvg', () => { + expect(component.$el.querySelector('.js-commit-icon').children).toContain('svg'); + }); + + describe('Given commit title and author props', () => { + it('should render a link to the author profile', () => { + expect( + component.$el.querySelector('.commit-title .avatar-image-container').getAttribute('href'), + ).toEqual(props.author.web_url); + }); + + it('Should render the author avatar with title and alt attributes', () => { + expect( + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('title'), + ).toContain(props.author.username); + expect( + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('alt'), + ).toContain(`${props.author.username}'s avatar`); + }); + }); + + it('should render the commit title', () => { + expect( + component.$el.querySelector('a.commit-row-message').getAttribute('href'), + ).toEqual(props.commitUrl); + expect( + component.$el.querySelector('a.commit-row-message').textContent, + ).toContain(props.title); + }); + }); + + describe('When commit title is not provided', () => { + it('should render default message', () => { + props = { + tag: false, + commitRef: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commitUrl: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + shortSha: 'b7836edd', + title: null, + author: {}, + }; + + component = new CommitComponent({ + propsData: props, + }).$mount(); + + expect( + component.$el.querySelector('.commit-title span').textContent, + ).toContain('Cant find HEAD commit for this branch'); + }); + }); +}); diff --git a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js new file mode 100644 index 00000000000..699625cdbb7 --- /dev/null +++ b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js @@ -0,0 +1,87 @@ +import Vue from 'vue'; +import tableRowComp from '~/vue_shared/components/pipelines_table_row'; +import pipeline from '../../commit/pipelines/mock_data'; + +describe('Pipelines Table Row', () => { + let component; + + beforeEach(() => { + const PipelinesTableRowComponent = Vue.extend(tableRowComp); + + component = new PipelinesTableRowComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + pipeline, + service: {}, + }, + }).$mount(); + }); + + it('should render a table row', () => { + expect(component.$el).toEqual('TR'); + }); + + describe('status column', () => { + it('should render a pipeline link', () => { + expect( + component.$el.querySelector('td.commit-link a').getAttribute('href'), + ).toEqual(pipeline.path); + }); + + it('should render status text', () => { + expect( + component.$el.querySelector('td.commit-link a').textContent, + ).toContain(pipeline.details.status.text); + }); + }); + + describe('information column', () => { + it('should render a pipeline link', () => { + expect( + component.$el.querySelector('td:nth-child(2) a').getAttribute('href'), + ).toEqual(pipeline.path); + }); + + it('should render pipeline ID', () => { + expect( + component.$el.querySelector('td:nth-child(2) a > span').textContent, + ).toEqual(`#${pipeline.id}`); + }); + + describe('when a user is provided', () => { + it('should render user information', () => { + expect( + component.$el.querySelector('td:nth-child(2) a:nth-child(3)').getAttribute('href'), + ).toEqual(pipeline.user.web_url); + + expect( + component.$el.querySelector('td:nth-child(2) img').getAttribute('title'), + ).toEqual(pipeline.user.name); + }); + }); + }); + + describe('commit column', () => { + it('should render link to commit', () => { + expect( + component.$el.querySelector('td:nth-child(3) .commit-id').getAttribute('href'), + ).toEqual(pipeline.commit.commit_path); + }); + }); + + describe('stages column', () => { + it('should render an icon for each stage', () => { + expect( + component.$el.querySelectorAll('td:nth-child(4) .js-builds-dropdown-button').length, + ).toEqual(pipeline.details.stages.length); + }); + }); + + describe('actions column', () => { + it('should render the provided actions', () => { + expect( + component.$el.querySelectorAll('td:nth-child(6) ul li').length, + ).toEqual(pipeline.details.manual_actions.length); + }); + }); +}); diff --git a/spec/javascripts/vue_shared/components/pipelines_table_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_spec.js new file mode 100644 index 00000000000..4d3ced944d7 --- /dev/null +++ b/spec/javascripts/vue_shared/components/pipelines_table_spec.js @@ -0,0 +1,67 @@ +import Vue from 'vue'; +import pipelinesTableComp from '~/vue_shared/components/pipelines_table'; +import '~/lib/utils/datetime_utility'; +import pipeline from '../../commit/pipelines/mock_data'; + +describe('Pipelines Table', () => { + let PipelinesTableComponent; + + beforeEach(() => { + PipelinesTableComponent = Vue.extend(pipelinesTableComp); + }); + + describe('table', () => { + let component; + beforeEach(() => { + component = new PipelinesTableComponent({ + propsData: { + pipelines: [], + service: {}, + }, + }).$mount(); + }); + + afterEach(() => { + component.$destroy(); + }); + + it('should render a table', () => { + expect(component.$el).toEqual('TABLE'); + }); + + it('should render table head with correct columns', () => { + expect(component.$el.querySelector('th.js-pipeline-status').textContent).toEqual('Status'); + expect(component.$el.querySelector('th.js-pipeline-info').textContent).toEqual('Pipeline'); + expect(component.$el.querySelector('th.js-pipeline-commit').textContent).toEqual('Commit'); + expect(component.$el.querySelector('th.js-pipeline-stages').textContent).toEqual('Stages'); + expect(component.$el.querySelector('th.js-pipeline-date').textContent).toEqual(''); + expect(component.$el.querySelector('th.js-pipeline-actions').textContent).toEqual(''); + }); + }); + + describe('without data', () => { + it('should render an empty table', () => { + const component = new PipelinesTableComponent({ + propsData: { + pipelines: [], + service: {}, + }, + }).$mount(); + expect(component.$el.querySelectorAll('tbody tr').length).toEqual(0); + }); + }); + + describe('with data', () => { + it('should render rows', () => { + const component = new PipelinesTableComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + pipelines: [pipeline], + service: {}, + }, + }).$mount(); + + expect(component.$el.querySelectorAll('tbody tr').length).toEqual(1); + }); + }); +}); diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js new file mode 100644 index 00000000000..96038718191 --- /dev/null +++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js @@ -0,0 +1,150 @@ +import Vue from 'vue'; +import paginationComp from '~/vue_shared/components/table_pagination'; +import '~/lib/utils/common_utils'; + +describe('Pagination component', () => { + let component; + let PaginationComponent; + + const changeChanges = { + one: '', + }; + + const change = (one) => { + changeChanges.one = one; + }; + + beforeEach(() => { + PaginationComponent = Vue.extend(paginationComp); + }); + + it('should render and start at page 1', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 2, + previousPage: '', + }, + change, + }, + }).$mount(); + + expect(component.$el.classList).toContain('gl-pagination'); + + component.changePage({ target: { innerText: '1' } }); + + expect(changeChanges.one).toEqual(1); + }); + + it('should go to the previous page', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 3, + previousPage: 1, + }, + change, + }, + }).$mount(); + + component.changePage({ target: { innerText: 'Prev' } }); + + expect(changeChanges.one).toEqual(1); + }); + + it('should go to the next page', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 5, + previousPage: 3, + }, + change, + }, + }).$mount(); + + component.changePage({ target: { innerText: 'Next' } }); + + expect(changeChanges.one).toEqual(5); + }); + + it('should go to the last page', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 5, + previousPage: 3, + }, + change, + }, + }).$mount(); + + component.changePage({ target: { innerText: 'Last »' } }); + + expect(changeChanges.one).toEqual(10); + }); + + it('should go to the first page', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 5, + previousPage: 3, + }, + change, + }, + }).$mount(); + + component.changePage({ target: { innerText: '« First' } }); + + expect(changeChanges.one).toEqual(1); + }); + + it('should do nothing', () => { + component = new PaginationComponent({ + propsData: { + pageInfo: { + totalPages: 10, + nextPage: 2, + previousPage: '', + }, + change, + }, + }).$mount(); + + component.changePage({ target: { innerText: '...' } }); + + expect(changeChanges.one).toEqual(1); + }); +}); + +describe('paramHelper', () => { + afterEach(() => { + window.history.pushState({}, null, ''); + }); + + it('can parse url parameters correctly', () => { + window.history.pushState({}, null, '?scope=all&p=2'); + + const scope = gl.utils.getParameterByName('scope'); + const p = gl.utils.getParameterByName('p'); + + expect(scope).toEqual('all'); + expect(p).toEqual('2'); + }); + + it('returns null if param not in url', () => { + window.history.pushState({}, null, '?p=2'); + + const scope = gl.utils.getParameterByName('scope'); + const p = gl.utils.getParameterByName('p'); + + expect(scope).toEqual(null); + expect(p).toEqual('2'); + }); +}); |