Commit 8807c85f authored by Phil Hughes's avatar Phil Hughes

Merge branch 'migrate-pipeliness-specs' into 'master'

Migrate pipelines specs to Jest + VTU

See merge request gitlab-org/gitlab!20656
parents c153894e 0f87e8a5
import Vue from 'vue';
import { trimText } from 'helpers/text_helper';
import { mount } from '@vue/test-utils';
import JobItem from '~/pipelines/components/graph/job_item.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('pipeline graph job item', () => {
const JobComponent = Vue.extend(JobItem);
let component;
let wrapper;
const createWrapper = propsData => {
wrapper = mount(JobItem, { sync: false, attachToDocument: true, propsData });
};
const delayedJobFixture = getJSONFixture('jobs/delayed.json');
const mockJob = {
......@@ -28,27 +31,25 @@ describe('pipeline graph job item', () => {
};
afterEach(() => {
component.$destroy();
wrapper.destroy();
});
describe('name with link', () => {
it('should render the job name and status with a link', done => {
component = mountComponent(JobComponent, { job: mockJob });
createWrapper({ job: mockJob });
Vue.nextTick(() => {
const link = component.$el.querySelector('a');
wrapper.vm.$nextTick(() => {
const link = wrapper.find('a');
expect(link.getAttribute('href')).toEqual(mockJob.status.details_path);
expect(link.attributes('href')).toBe(mockJob.status.details_path);
expect(link.getAttribute('data-original-title')).toEqual(
expect(link.attributes('data-original-title')).toEqual(
`${mockJob.name} - ${mockJob.status.label}`,
);
expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
expect(wrapper.find('.js-status-icon-success')).toBeDefined();
expect(component.$el.querySelector('.ci-status-text').textContent.trim()).toEqual(
mockJob.name,
);
expect(trimText(wrapper.find('.ci-status-text').text())).toBe(mockJob.name);
done();
});
......@@ -57,7 +58,7 @@ describe('pipeline graph job item', () => {
describe('name without link', () => {
it('it should render status and name', () => {
component = mountComponent(JobComponent, {
createWrapper({
job: {
id: 4257,
name: 'test',
......@@ -72,36 +73,34 @@ describe('pipeline graph job item', () => {
},
});
expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
expect(component.$el.querySelector('a')).toBeNull();
expect(wrapper.find('.js-status-icon-success')).toBeDefined();
expect(wrapper.find('a').exists()).toBe(false);
expect(component.$el.querySelector('.ci-status-text').textContent.trim()).toEqual(
mockJob.name,
);
expect(trimText(wrapper.find('.ci-status-text').text())).toEqual(mockJob.name);
});
});
describe('action icon', () => {
it('it should render the action icon', () => {
component = mountComponent(JobComponent, { job: mockJob });
createWrapper({ job: mockJob });
expect(component.$el.querySelector('a.ci-action-icon-container')).toBeDefined();
expect(component.$el.querySelector('i.ci-action-icon-wrapper')).toBeDefined();
expect(wrapper.find('a.ci-action-icon-container')).toBeDefined();
expect(wrapper.find('i.ci-action-icon-wrapper')).toBeDefined();
});
});
it('should render provided class name', () => {
component = mountComponent(JobComponent, {
createWrapper({
job: mockJob,
cssClassJobName: 'css-class-job-name',
});
expect(component.$el.querySelector('a').classList.contains('css-class-job-name')).toBe(true);
expect(wrapper.find('a').classes()).toContain('css-class-job-name');
});
describe('status label', () => {
it('should not render status label when it is not provided', () => {
component = mountComponent(JobComponent, {
createWrapper({
job: {
id: 4258,
name: 'test',
......@@ -111,15 +110,13 @@ describe('pipeline graph job item', () => {
},
});
expect(
component.$el
.querySelector('.js-job-component-tooltip')
.getAttribute('data-original-title'),
).toEqual('test');
expect(wrapper.find('.js-job-component-tooltip').attributes('data-original-title')).toBe(
'test',
);
});
it('should not render status label when it is provided', () => {
component = mountComponent(JobComponent, {
createWrapper({
job: {
id: 4259,
name: 'test',
......@@ -131,25 +128,21 @@ describe('pipeline graph job item', () => {
},
});
expect(
component.$el
.querySelector('.js-job-component-tooltip')
.getAttribute('data-original-title'),
).toEqual('test - success');
expect(wrapper.find('.js-job-component-tooltip').attributes('data-original-title')).toEqual(
'test - success',
);
});
});
describe('for delayed job', () => {
it('displays remaining time in tooltip', () => {
component = mountComponent(JobComponent, {
createWrapper({
job: delayedJobFixture,
});
expect(
component.$el
.querySelector('.js-pipeline-graph-job-link')
.getAttribute('data-original-title'),
).toEqual(`delayed job - delayed manual action (${component.remainingTime})`);
expect(wrapper.find('.js-pipeline-graph-job-link').attributes('data-original-title')).toEqual(
`delayed job - delayed manual action (${wrapper.vm.remainingTime})`,
);
});
});
});
import Vue from 'vue';
import { mount } from '@vue/test-utils';
import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import mockData from './linked_pipelines_mock_data';
const mockPipeline = mockData.triggered[0];
describe('Linked pipeline', () => {
const Component = Vue.extend(LinkedPipelineComponent);
let vm;
let wrapper;
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('rendered output', () => {
......@@ -19,57 +18,61 @@ describe('Linked pipeline', () => {
};
beforeEach(() => {
vm = mountComponent(Component, props);
wrapper = mount(LinkedPipelineComponent, {
sync: false,
attachToDocument: true,
propsData: props,
});
});
it('should render a list item as the containing element', () => {
expect(vm.$el.tagName).toBe('LI');
expect(wrapper.is('li')).toBe(true);
});
it('should render a button', () => {
const linkElement = vm.$el.querySelector('.js-linked-pipeline-content');
const linkElement = wrapper.find('.js-linked-pipeline-content');
expect(linkElement).not.toBeNull();
expect(linkElement.exists()).toBe(true);
});
it('should render the project name', () => {
expect(vm.$el.innerText).toContain(props.pipeline.project.name);
expect(wrapper.text()).toContain(props.pipeline.project.name);
});
it('should render an svg within the status container', () => {
const pipelineStatusElement = vm.$el.querySelector('.js-linked-pipeline-status');
const pipelineStatusElement = wrapper.find('.js-linked-pipeline-status');
expect(pipelineStatusElement.querySelector('svg')).not.toBeNull();
expect(pipelineStatusElement.find('svg').exists()).toBe(true);
});
it('should render the pipeline status icon svg', () => {
expect(vm.$el.querySelector('.js-ci-status-icon-running')).not.toBeNull();
expect(vm.$el.querySelector('.js-ci-status-icon-running').innerHTML).toContain('<svg');
expect(wrapper.find('.js-ci-status-icon-running').exists()).toBe(true);
expect(wrapper.find('.js-ci-status-icon-running').html()).toContain('<svg');
});
it('should have a ci-status child component', () => {
expect(vm.$el.querySelector('.js-linked-pipeline-status')).not.toBeNull();
expect(wrapper.find('.js-linked-pipeline-status').exists()).toBe(true);
});
it('should render the pipeline id', () => {
expect(vm.$el.innerText).toContain(`#${props.pipeline.id}`);
expect(wrapper.text()).toContain(`#${props.pipeline.id}`);
});
it('should correctly compute the tooltip text', () => {
expect(vm.tooltipText).toContain(mockPipeline.project.name);
expect(vm.tooltipText).toContain(mockPipeline.details.status.label);
expect(wrapper.vm.tooltipText).toContain(mockPipeline.project.name);
expect(wrapper.vm.tooltipText).toContain(mockPipeline.details.status.label);
});
it('should render the tooltip text as the title attribute', () => {
const tooltipRef = vm.$el.querySelector('.js-linked-pipeline-content');
const titleAttr = tooltipRef.getAttribute('data-original-title');
const tooltipRef = wrapper.find('.js-linked-pipeline-content');
const titleAttr = tooltipRef.attributes('data-original-title');
expect(titleAttr).toContain(mockPipeline.project.name);
expect(titleAttr).toContain(mockPipeline.details.status.label);
});
it('does not render the loading icon when isLoading is false', () => {
expect(vm.$el.querySelector('.js-linked-pipeline-loading')).toBeNull();
expect(wrapper.find('.js-linked-pipeline-loading').exists()).toBe(false);
});
});
......@@ -79,11 +82,15 @@ describe('Linked pipeline', () => {
};
beforeEach(() => {
vm = mountComponent(Component, props);
wrapper = mount(LinkedPipelineComponent, {
sync: false,
attachToDocument: true,
propsData: props,
});
});
it('renders a loading icon', () => {
expect(vm.$el.querySelector('.js-linked-pipeline-loading')).not.toBeNull();
expect(wrapper.find('.js-linked-pipeline-loading').exists()).toBe(true);
});
});
......@@ -93,21 +100,25 @@ describe('Linked pipeline', () => {
};
beforeEach(() => {
vm = mountComponent(Component, props);
wrapper = mount(LinkedPipelineComponent, {
sync: false,
attachToDocument: true,
propsData: props,
});
});
it('emits `pipelineClicked` event', () => {
spyOn(vm, '$emit');
vm.$el.querySelector('button').click();
jest.spyOn(wrapper.vm, '$emit');
wrapper.find('button').trigger('click');
expect(vm.$emit).toHaveBeenCalledWith('pipelineClicked');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('pipelineClicked');
});
it('should emit `bv::hide::tooltip` to close the tooltip', () => {
spyOn(vm.$root, '$emit');
vm.$el.querySelector('button').click();
jest.spyOn(wrapper.vm.$root, '$emit');
wrapper.find('button').trigger('click');
expect(vm.$root.$emit.calls.argsFor(0)).toEqual([
expect(wrapper.vm.$root.$emit.mock.calls[0]).toEqual([
'bv::hide::tooltip',
'js-linked-pipeline-132',
]);
......
This diff is collapsed.
import $ from 'jquery';
import { trimText } from 'helpers/text_helper';
import { shallowMount } from '@vue/test-utils';
import PipelineUrlComponent from '~/pipelines/components/pipeline_url.vue';
$.fn.popover = () => {};
describe('Pipeline Url Component', () => {
let wrapper;
const createComponent = props => {
wrapper = shallowMount(PipelineUrlComponent, {
sync: false,
attachToDocument: true,
propsData: props,
});
};
afterEach(() => {
wrapper.destroy();
});
it('should render a table cell', () => {
createComponent({
pipeline: {
id: 1,
path: 'foo',
flags: {},
},
autoDevopsHelpPath: 'foo',
});
expect(wrapper.attributes('class')).toContain('table-section');
});
it('should render a link the provided path and id', () => {
createComponent({
pipeline: {
id: 1,
path: 'foo',
flags: {},
},
autoDevopsHelpPath: 'foo',
});
expect(wrapper.find('.js-pipeline-url-link').attributes('href')).toBe('foo');
expect(wrapper.find('.js-pipeline-url-link span').text()).toBe('#1');
});
it('should render latest, yaml invalid, merge request, and stuck flags when provided', () => {
createComponent({
pipeline: {
id: 1,
path: 'foo',
flags: {
latest: true,
yaml_errors: true,
stuck: true,
merge_request_pipeline: true,
detached_merge_request_pipeline: true,
},
},
autoDevopsHelpPath: 'foo',
});
expect(wrapper.find('.js-pipeline-url-latest').text()).toContain('latest');
expect(wrapper.find('.js-pipeline-url-yaml').text()).toContain('yaml invalid');
expect(wrapper.find('.js-pipeline-url-stuck').text()).toContain('stuck');
expect(wrapper.find('.js-pipeline-url-detached').text()).toContain('detached');
});
it('should render a badge for autodevops', () => {
createComponent({
pipeline: {
id: 1,
path: 'foo',
flags: {
latest: true,
yaml_errors: true,
stuck: true,
auto_devops: true,
},
},
autoDevopsHelpPath: 'foo',
});
expect(trimText(wrapper.find('.js-pipeline-url-autodevops').text())).toEqual('Auto DevOps');
});
it('should render error badge when pipeline has a failure reason set', () => {
createComponent({
pipeline: {
id: 1,
path: 'foo',
flags: {
failure_reason: true,
},
failure_reason: 'some reason',
},
autoDevopsHelpPath: 'foo',
});
expect(wrapper.find('.js-pipeline-url-failure').text()).toContain('error');
expect(wrapper.find('.js-pipeline-url-failure').attributes('data-original-title')).toContain(
'some reason',
);
});
});
import Vue from 'vue';
import pipelineUrlComp from '~/pipelines/components/pipeline_url.vue';
describe('Pipeline Url Component', () => {
let PipelineUrlComponent;
beforeEach(() => {
PipelineUrlComponent = Vue.extend(pipelineUrlComp);
});
it('should render a table cell', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {},
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.getAttribute('class')).toContain('table-section');
});
it('should render a link the provided path and id', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {},
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.querySelector('.js-pipeline-url-link').getAttribute('href')).toEqual(
'foo',
);
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1');
});
it('should render latest, yaml invalid, merge request, and stuck flags when provided', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {
latest: true,
yaml_errors: true,
stuck: true,
merge_request_pipeline: true,
detached_merge_request_pipeline: true,
},
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.querySelector('.js-pipeline-url-latest').textContent).toContain('latest');
expect(component.$el.querySelector('.js-pipeline-url-yaml').textContent).toContain(
'yaml invalid',
);
expect(component.$el.querySelector('.js-pipeline-url-stuck').textContent).toContain('stuck');
expect(component.$el.querySelector('.js-pipeline-url-detached').textContent).toContain(
'detached',
);
});
it('should render a badge for autodevops', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {
latest: true,
yaml_errors: true,
stuck: true,
auto_devops: true,
},
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.querySelector('.js-pipeline-url-autodevops').textContent.trim()).toEqual(
'Auto DevOps',
);
});
it('should render error badge when pipeline has a failure reason set', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {
failure_reason: true,
},
failure_reason: 'some reason',
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.querySelector('.js-pipeline-url-failure').textContent).toContain('error');
expect(
component.$el.querySelector('.js-pipeline-url-failure').getAttribute('data-original-title'),
).toContain('some reason');
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment