Commit 6b956d95 authored by pburdette's avatar pburdette Committed by Payton Burdette

Refactor commit pipelines table spec

Refactor the spec to use best practices
and port over to vue test utils.
parent fb96d801
import '~/commons'; import { GlEmptyState, GlLoadingIcon, GlModal, GlTable } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import mountComponent from 'helpers/vue_mount_component_helper'; import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api'; import Api from '~/api';
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue'; import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
describe('Pipelines table in Commits and Merge requests', () => { describe('Pipelines table in Commits and Merge requests', () => {
const jsonFixtureName = 'pipelines/pipelines.json'; const jsonFixtureName = 'pipelines/pipelines.json';
let wrapper;
let pipeline; let pipeline;
let PipelinesTable;
let mock; let mock;
let vm;
const props = { const defaultProps = {
endpoint: 'endpoint.json', endpoint: 'endpoint.json',
emptyStateSvgPath: 'foo', emptyStateSvgPath: 'foo',
errorStateSvgPath: 'foo', errorStateSvgPath: 'foo',
}; };
const findRunPipelineBtn = () => vm.$el.querySelector('[data-testid="run_pipeline_button"]'); const findRunPipelineBtn = () => wrapper.findByTestId('run_pipeline_button');
const findRunPipelineBtnMobile = () => const findRunPipelineBtnMobile = () => wrapper.findByTestId('run_pipeline_button_mobile');
vm.$el.querySelector('[data-testid="run_pipeline_button_mobile"]'); const findLoadingState = () => wrapper.findComponent(GlLoadingIcon);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findTable = () => wrapper.findComponent(GlTable);
const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findModal = () => wrapper.findComponent(GlModal);
const createComponent = (props = defaultProps) => {
wrapper = extendedWrapper(
mount(PipelinesTable, {
propsData: {
...props,
},
}),
);
};
beforeEach(() => { beforeEach(() => {
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
const { pipelines } = getJSONFixture(jsonFixtureName); const { pipelines } = getJSONFixture(jsonFixtureName);
PipelinesTable = Vue.extend(pipelinesTable);
pipeline = pipelines.find((p) => p.user !== null && p.commit !== null); pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
mock.restore(); mock.restore();
}); });
describe('successful request', () => { describe('successful request', () => {
describe('without pipelines', () => { describe('without pipelines', () => {
beforeEach(() => { beforeEach(async () => {
mock.onGet('endpoint.json').reply(200, []); mock.onGet('endpoint.json').reply(200, []);
vm = mountComponent(PipelinesTable, props); createComponent();
});
it('should render the empty state', (done) => { await waitForPromises();
setImmediate(() => {
expect(vm.$el.querySelector('.empty-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
done();
}); });
it('should render the empty state', () => {
expect(findTableRows()).toHaveLength(0);
expect(findLoadingState().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(false);
}); });
}); });
describe('with pipelines', () => { describe('with pipelines', () => {
beforeEach(() => { beforeEach(async () => {
mock.onGet('endpoint.json').reply(200, [pipeline]); mock.onGet('endpoint.json').reply(200, [pipeline]);
vm = mountComponent(PipelinesTable, props);
});
it('should render a table with the received pipelines', (done) => { createComponent();
setImmediate(() => {
expect(vm.$el.querySelectorAll('.ci-table .commit').length).toEqual(1); await waitForPromises();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
expect(vm.$el.querySelector('.empty-state')).toBe(null);
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
done();
}); });
it('should render a table with the received pipelines', () => {
expect(findTable().exists()).toBe(true);
expect(findTableRows()).toHaveLength(1);
expect(findLoadingState().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(false);
}); });
describe('with pagination', () => { describe('with pagination', () => {
it('should make an API request when using pagination', (done) => { it('should make an API request when using pagination', async () => {
setImmediate(() => { jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
jest.spyOn(vm, 'updateContent').mockImplementation(() => {});
vm.store.state.pageInfo = { await wrapper.setData({
store: {
state: {
pageInfo: {
page: 1, page: 1,
total: 10, total: 10,
perPage: 2, perPage: 2,
nextPage: 2, nextPage: 2,
totalPages: 5, totalPages: 5,
}; },
},
},
});
vm.$nextTick(() => { wrapper.find('.next-page-item').trigger('click');
vm.$el.querySelector('.next-page-item').click();
expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' }); expect(wrapper.vm.updateContent).toHaveBeenCalledWith({ page: '2' });
done();
});
});
}); });
}); });
}); });
describe('pipeline badge counts', () => { describe('pipeline badge counts', () => {
beforeEach(() => { it('should receive update-pipelines-count event', (done) => {
mock.onGet('endpoint.json').reply(200, [pipeline]); mock.onGet('endpoint.json').reply(200, [pipeline]);
});
it('should receive update-pipelines-count event', (done) => {
const element = document.createElement('div'); const element = document.createElement('div');
document.body.appendChild(element); document.body.appendChild(element);
...@@ -108,9 +120,9 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -108,9 +120,9 @@ describe('Pipelines table in Commits and Merge requests', () => {
done(); done();
}); });
vm = mountComponent(PipelinesTable, props); createComponent();
element.appendChild(vm.$el); element.appendChild(wrapper.vm.$el);
}); });
}); });
}); });
...@@ -123,50 +135,45 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -123,50 +135,45 @@ describe('Pipelines table in Commits and Merge requests', () => {
}); });
describe('when latest pipeline has detached flag', () => { describe('when latest pipeline has detached flag', () => {
it('renders the run pipeline button', (done) => { it('renders the run pipeline button', async () => {
pipelineCopy.flags.detached_merge_request_pipeline = true; pipelineCopy.flags.detached_merge_request_pipeline = true;
pipelineCopy.flags.merge_request_pipeline = true; pipelineCopy.flags.merge_request_pipeline = true;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]); mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
vm = mountComponent(PipelinesTable, { ...props }); createComponent();
setImmediate(() => { await waitForPromises();
expect(findRunPipelineBtn()).not.toBeNull();
expect(findRunPipelineBtnMobile()).not.toBeNull(); expect(findRunPipelineBtn().exists()).toBe(true);
done(); expect(findRunPipelineBtnMobile().exists()).toBe(true);
});
}); });
}); });
describe('when latest pipeline does not have detached flag', () => { describe('when latest pipeline does not have detached flag', () => {
it('does not render the run pipeline button', (done) => { it('does not render the run pipeline button', async () => {
pipelineCopy.flags.detached_merge_request_pipeline = false; pipelineCopy.flags.detached_merge_request_pipeline = false;
pipelineCopy.flags.merge_request_pipeline = false; pipelineCopy.flags.merge_request_pipeline = false;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]); mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
vm = mountComponent(PipelinesTable, { ...props }); createComponent();
setImmediate(() => { await waitForPromises();
expect(findRunPipelineBtn()).toBeNull();
expect(findRunPipelineBtnMobile()).toBeNull(); expect(findRunPipelineBtn().exists()).toBe(false);
done(); expect(findRunPipelineBtnMobile().exists()).toBe(false);
});
}); });
}); });
describe('on click', () => { describe('on click', () => {
const findModal = () => beforeEach(async () => {
document.querySelector('#create-pipeline-for-fork-merge-request-modal');
beforeEach((done) => {
pipelineCopy.flags.detached_merge_request_pipeline = true; pipelineCopy.flags.detached_merge_request_pipeline = true;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]); mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
vm = mountComponent(PipelinesTable, { createComponent({
...props, ...defaultProps,
canRunPipeline: true, canRunPipeline: true,
projectId: '5', projectId: '5',
mergeRequestId: 3, mergeRequestId: 3,
...@@ -174,59 +181,39 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -174,59 +181,39 @@ describe('Pipelines table in Commits and Merge requests', () => {
jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve()); jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
setImmediate(() => { await waitForPromises();
done();
}); });
});
it('on desktop, shows a loading button', (done) => {
findRunPipelineBtn().click();
vm.$nextTick(() => { it('on desktop, shows a loading button', async () => {
expect(findModal()).toBeNull(); await findRunPipelineBtn().trigger('click');
expect(findRunPipelineBtn().disabled).toBe(true); expect(findRunPipelineBtn().props('loading')).toBe(true);
expect(findRunPipelineBtn().querySelector('.gl-spinner')).not.toBeNull();
setImmediate(() => { await waitForPromises();
expect(findRunPipelineBtn().disabled).toBe(false);
expect(findRunPipelineBtn().querySelector('.gl-spinner')).toBeNull();
done(); expect(findRunPipelineBtn().props('loading')).toBe(false);
}); });
});
});
it('on mobile, shows a loading button', (done) => {
findRunPipelineBtnMobile().click();
vm.$nextTick(() => { it('on mobile, shows a loading button', async () => {
expect(findModal()).toBeNull(); await findRunPipelineBtnMobile().trigger('click');
expect(findModal()).toBeNull(); expect(findRunPipelineBtn().props('loading')).toBe(true);
expect(findRunPipelineBtn().querySelector('.gl-spinner')).not.toBeNull();
setImmediate(() => { await waitForPromises();
expect(findRunPipelineBtn().disabled).toBe(false);
expect(findRunPipelineBtn().querySelector('.gl-spinner')).toBeNull();
done(); expect(findRunPipelineBtn().props('disabled')).toBe(false);
}); expect(findRunPipelineBtn().props('loading')).toBe(false);
});
}); });
}); });
describe('on click for fork merge request', () => { describe('on click for fork merge request', () => {
const findModal = () => beforeEach(async () => {
document.querySelector('#create-pipeline-for-fork-merge-request-modal');
beforeEach((done) => {
pipelineCopy.flags.detached_merge_request_pipeline = true; pipelineCopy.flags.detached_merge_request_pipeline = true;
mock.onGet('endpoint.json').reply(200, [pipelineCopy]); mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
vm = mountComponent(PipelinesTable, { createComponent({
...props, ...defaultProps,
projectId: '5', projectId: '5',
mergeRequestId: 3, mergeRequestId: 3,
canCreatePipelineInTargetProject: true, canCreatePipelineInTargetProject: true,
...@@ -236,45 +223,39 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -236,45 +223,39 @@ describe('Pipelines table in Commits and Merge requests', () => {
jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve()); jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
setImmediate(() => { await waitForPromises();
done();
});
}); });
it('on desktop, shows a security warning modal', (done) => { it('on desktop, shows a security warning modal', async () => {
findRunPipelineBtn().click(); await findRunPipelineBtn().trigger('click');
await wrapper.vm.$nextTick();
vm.$nextTick(() => {
expect(findModal()).not.toBeNull(); expect(findModal()).not.toBeNull();
done();
});
}); });
it('on mobile, shows a security warning modal', (done) => { it('on mobile, shows a security warning modal', async () => {
findRunPipelineBtnMobile().click(); await findRunPipelineBtnMobile().trigger('click');
vm.$nextTick(() => {
expect(findModal()).not.toBeNull(); expect(findModal()).not.toBeNull();
done();
});
}); });
}); });
}); });
describe('unsuccessfull request', () => { describe('unsuccessfull request', () => {
beforeEach(() => { beforeEach(async () => {
mock.onGet('endpoint.json').reply(500, []); mock.onGet('endpoint.json').reply(500, []);
vm = mountComponent(PipelinesTable, props); createComponent();
});
it('should render error state', (done) => { await waitForPromises();
setImmediate(() => {
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
expect(vm.$el.querySelector('.ci-table')).toBe(null);
done();
}); });
it('should render error state', () => {
expect(findEmptyState().exists()).toBe(true);
expect(findEmptyState().text()).toBe(
'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
);
}); });
}); });
}); });
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