Commit b40d1ce7 authored by Miguel Rincon's avatar Miguel Rincon

Merge branch '320932-move-spec-to-vue-test-utils' into 'master'

Refactor commit pipelines table spec

See merge request gitlab-org/gitlab!62031
parents fe88471c 38f3bf58
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 = {
endpoint: 'endpoint.json',
emptyStateSvgPath: '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 = {}) => {
wrapper = extendedWrapper(
mount(PipelinesTable, {
propsData: {
endpoint: 'endpoint.json',
emptyStateSvgPath: 'foo',
errorStateSvgPath: 'foo',
...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();
await waitForPromises();
}); });
it('should render the empty state', (done) => { it('should render the empty state', () => {
setImmediate(() => { expect(findTableRows()).toHaveLength(0);
expect(vm.$el.querySelector('.empty-state')).toBeDefined(); expect(findLoadingState().exists()).toBe(false);
expect(vm.$el.querySelector('.realtime-loading')).toBe(null); expect(findEmptyState().exists()).toBe(false);
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
done();
});
}); });
}); });
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);
createComponent();
await waitForPromises();
}); });
it('should render a table with the received pipelines', (done) => { it('should render a table with the received pipelines', () => {
setImmediate(() => { expect(findTable().exists()).toBe(true);
expect(vm.$el.querySelectorAll('.ci-table .commit').length).toEqual(1); expect(findTableRows()).toHaveLength(1);
expect(vm.$el.querySelector('.realtime-loading')).toBe(null); expect(findLoadingState().exists()).toBe(false);
expect(vm.$el.querySelector('.empty-state')).toBe(null); expect(findEmptyState().exists()).toBe(false);
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
done();
});
}); });
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(() => {});
await wrapper.setData({
vm.store.state.pageInfo = { store: {
page: 1, state: {
total: 10, pageInfo: {
perPage: 2, page: 1,
nextPage: 2, total: 10,
totalPages: 5, perPage: 2,
}; nextPage: 2,
totalPages: 5,
vm.$nextTick(() => { },
vm.$el.querySelector('.next-page-item').click(); },
},
expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
done();
});
}); });
});
});
});
describe('pipeline badge counts', () => { wrapper.find('.next-page-item').trigger('click');
beforeEach(() => {
mock.onGet('endpoint.json').reply(200, [pipeline]); expect(wrapper.vm.updateContent).toHaveBeenCalledWith({ page: '2' });
});
}); });
it('should receive update-pipelines-count event', (done) => { describe('pipeline badge counts', () => {
const element = document.createElement('div'); it('should receive update-pipelines-count event', (done) => {
document.body.appendChild(element); const element = document.createElement('div');
document.body.appendChild(element);
element.addEventListener('update-pipelines-count', (event) => { element.addEventListener('update-pipelines-count', (event) => {
expect(event.detail.pipelines).toEqual([pipeline]); expect(event.detail.pipelines).toEqual([pipeline]);
done(); done();
}); });
vm = mountComponent(PipelinesTable, props); createComponent();
element.appendChild(vm.$el); element.appendChild(wrapper.vm.$el);
});
}); });
}); });
}); });
...@@ -123,50 +130,44 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -123,50 +130,44 @@ 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,
canRunPipeline: true, canRunPipeline: true,
projectId: '5', projectId: '5',
mergeRequestId: 3, mergeRequestId: 3,
...@@ -174,59 +175,38 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -174,59 +175,38 @@ 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) => { it('on desktop, shows a loading button', async () => {
findRunPipelineBtn().click(); await findRunPipelineBtn().trigger('click');
vm.$nextTick(() => {
expect(findModal()).toBeNull();
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) => { it('on mobile, shows a loading button', async () => {
findRunPipelineBtnMobile().click(); await findRunPipelineBtnMobile().trigger('click');
vm.$nextTick(() => {
expect(findModal()).toBeNull();
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,
projectId: '5', projectId: '5',
mergeRequestId: 3, mergeRequestId: 3,
canCreatePipelineInTargetProject: true, canCreatePipelineInTargetProject: true,
...@@ -236,45 +216,38 @@ describe('Pipelines table in Commits and Merge requests', () => { ...@@ -236,45 +216,38 @@ 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');
vm.$nextTick(() => { await wrapper.vm.$nextTick();
expect(findModal()).not.toBeNull();
done(); expect(findModal()).not.toBeNull();
});
}); });
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();
await waitForPromises();
}); });
it('should render error state', (done) => { it('should render error state', () => {
setImmediate(() => { expect(findEmptyState().text()).toBe(
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBeDefined(); 'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
expect(vm.$el.querySelector('.realtime-loading')).toBe(null); );
expect(vm.$el.querySelector('.ci-table')).toBe(null);
done();
});
}); });
}); });
}); });
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