Commit 0b8d508b authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '194227-migrate-spec-javascripts-deploy_keys-to-jest' into 'master'

Migrate deploy_keys to Jest

Closes #194227

See merge request gitlab-org/gitlab!30145
parents eca8d9af f4e148e0
import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '~/deploy_keys/eventhub';
import actionBtn from '~/deploy_keys/components/action_btn.vue';
describe('Deploy keys action btn', () => {
const data = getJSONFixture('deploy_keys/keys.json');
const deployKey = data.enabled_keys[0];
let wrapper;
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
beforeEach(() => {
wrapper = shallowMount(actionBtn, {
propsData: {
deployKey,
type: 'enable',
},
slots: {
default: 'Enable',
},
});
});
it('renders the default slot', () => {
expect(wrapper.text()).toBe('Enable');
});
it('sends eventHub event with btn type', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
wrapper.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('enable.key', deployKey, expect.anything());
});
});
it('shows loading spinner after click', () => {
wrapper.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
it('disables button after click', () => {
wrapper.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.attributes('disabled')).toBe('disabled');
});
});
});
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import eventHub from '~/deploy_keys/eventhub';
import deployKeysApp from '~/deploy_keys/components/app.vue';
const TEST_ENDPOINT = `${TEST_HOST}/dummy/`;
describe('Deploy keys app component', () => {
const data = getJSONFixture('deploy_keys/keys.json');
let wrapper;
let mock;
const mountComponent = () => {
wrapper = mount(deployKeysApp, {
propsData: {
endpoint: TEST_ENDPOINT,
projectId: '8',
},
});
return waitForPromises();
};
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet(TEST_ENDPOINT).reply(200, data);
});
afterEach(() => {
wrapper.destroy();
mock.restore();
});
const findLoadingIcon = () => wrapper.find('.gl-spinner');
const findKeyPanels = () => wrapper.findAll('.deploy-keys .nav-links li');
it('renders loading icon while waiting for request', () => {
mock.onGet(TEST_ENDPOINT).reply(() => new Promise());
mountComponent();
return wrapper.vm.$nextTick().then(() => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
it('renders keys panels', () => {
return mountComponent().then(() => {
expect(findKeyPanels().length).toBe(3);
});
});
it.each`
selector | label | count
${'.js-deployKeys-tab-enabled_keys'} | ${'Enabled deploy keys'} | ${1}
${'.js-deployKeys-tab-available_project_keys'} | ${'Privately accessible deploy keys'} | ${0}
${'.js-deployKeys-tab-public_keys'} | ${'Publicly accessible deploy keys'} | ${1}
`('$selector title is $label with keys count equal to $count', ({ selector, label, count }) => {
return mountComponent().then(() => {
const element = wrapper.find(selector);
expect(element.exists()).toBe(true);
expect(element.text().trim()).toContain(label);
expect(
element
.find('.badge')
.text()
.trim(),
).toBe(count.toString());
});
});
it('does not render key panels when keys object is empty', () => {
mock.onGet(TEST_ENDPOINT).reply(200, []);
return mountComponent().then(() => {
expect(findKeyPanels().length).toBe(0);
});
});
it('re-fetches deploy keys when enabling a key', () => {
const key = data.public_keys[0];
return mountComponent()
.then(() => {
jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
jest.spyOn(wrapper.vm.service, 'enableKey').mockImplementation(() => Promise.resolve());
eventHub.$emit('enable.key', key);
return wrapper.vm.$nextTick();
})
.then(() => {
expect(wrapper.vm.service.enableKey).toHaveBeenCalledWith(key.id);
expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
});
it('re-fetches deploy keys when disabling a key', () => {
const key = data.public_keys[0];
return mountComponent()
.then(() => {
jest.spyOn(window, 'confirm').mockReturnValue(true);
jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
eventHub.$emit('disable.key', key);
return wrapper.vm.$nextTick();
})
.then(() => {
expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
});
it('calls disableKey when removing a key', () => {
const key = data.public_keys[0];
return mountComponent()
.then(() => {
jest.spyOn(window, 'confirm').mockReturnValue(true);
jest.spyOn(wrapper.vm.service, 'getKeys').mockImplementation(() => {});
jest.spyOn(wrapper.vm.service, 'disableKey').mockImplementation(() => Promise.resolve());
eventHub.$emit('remove.key', key);
return wrapper.vm.$nextTick();
})
.then(() => {
expect(wrapper.vm.service.disableKey).toHaveBeenCalledWith(key.id);
expect(wrapper.vm.service.getKeys).toHaveBeenCalled();
});
});
it('hasKeys returns true when there are keys', () => {
return mountComponent().then(() => {
expect(wrapper.vm.hasKeys).toEqual(3);
});
});
});
import { mount } from '@vue/test-utils';
import DeployKeysStore from '~/deploy_keys/store';
import key from '~/deploy_keys/components/key.vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Deploy keys key', () => {
let wrapper;
let store;
const data = getJSONFixture('deploy_keys/keys.json');
const findTextAndTrim = selector =>
wrapper
.find(selector)
.text()
.trim();
const createComponent = propsData => {
wrapper = mount(key, {
propsData: {
store,
endpoint: 'https://test.host/dummy/endpoint',
...propsData,
},
});
};
beforeEach(() => {
store = new DeployKeysStore();
store.keys = data;
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('enabled key', () => {
const deployKey = data.enabled_keys[0];
it('renders the keys title', () => {
createComponent({ deployKey });
expect(findTextAndTrim('.title')).toContain('My title');
});
it('renders human friendly formatted created date', () => {
createComponent({ deployKey });
expect(findTextAndTrim('.key-created-at')).toBe(
`${getTimeago().format(deployKey.created_at)}`,
);
});
it('shows pencil button for editing', () => {
createComponent({ deployKey });
expect(wrapper.find('.btn .ic-pencil')).toExist();
});
it('shows disable button when the project is not deletable', () => {
createComponent({ deployKey });
expect(wrapper.find('.btn .ic-cancel')).toExist();
});
it('shows remove button when the project is deletable', () => {
createComponent({
deployKey: { ...deployKey, destroyed_when_orphaned: true, almost_orphaned: true },
});
expect(wrapper.find('.btn .ic-remove')).toExist();
});
});
describe('deploy key labels', () => {
const deployKey = data.enabled_keys[0];
const deployKeysProjects = [...deployKey.deploy_keys_projects];
it('shows write access title when key has write access', () => {
deployKeysProjects[0] = { ...deployKeysProjects[0], can_push: true };
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: deployKeysProjects } });
expect(wrapper.find('.deploy-project-label').attributes('data-original-title')).toBe(
'Write access allowed',
);
});
it('does not show write access title when key has write access', () => {
deployKeysProjects[0] = { ...deployKeysProjects[0], can_push: false };
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: deployKeysProjects } });
expect(wrapper.find('.deploy-project-label').attributes('data-original-title')).toBe(
'Read access only',
);
});
it('shows expandable button if more than two projects', () => {
createComponent({ deployKey });
const labels = wrapper.findAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels.at(1).text()).toContain('others');
expect(labels.at(1).attributes('data-original-title')).toContain('Expand');
});
it('expands all project labels after click', () => {
createComponent({ deployKey });
const { length } = deployKey.deploy_keys_projects;
wrapper
.findAll('.deploy-project-label')
.at(1)
.trigger('click');
return wrapper.vm.$nextTick().then(() => {
const labels = wrapper.findAll('.deploy-project-label');
expect(labels.length).toBe(length);
expect(labels.at(1).text()).not.toContain(`+${length} others`);
expect(labels.at(1).attributes('data-original-title')).not.toContain('Expand');
});
});
it('shows two projects', () => {
createComponent({
deployKey: { ...deployKey, deploy_keys_projects: [...deployKeysProjects].slice(0, 2) },
});
const labels = wrapper.findAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels.at(1).text()).toContain(deployKey.deploy_keys_projects[1].project.full_name);
});
});
describe('public keys', () => {
const deployKey = data.public_keys[0];
it('renders deploy keys without any enabled projects', () => {
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: [] } });
expect(findTextAndTrim('.deploy-project-list')).toBe('None');
});
it('shows enable button', () => {
createComponent({ deployKey });
expect(findTextAndTrim('.btn')).toBe('Enable');
});
it('shows pencil button for editing', () => {
createComponent({ deployKey });
expect(wrapper.find('.btn .ic-pencil')).toExist();
});
it('shows disable button when key is enabled', () => {
store.keys.enabled_keys.push(deployKey);
createComponent({ deployKey });
expect(wrapper.find('.btn .ic-cancel')).toExist();
});
});
});
import Vue from 'vue';
import { mount } from '@vue/test-utils';
import DeployKeysStore from '~/deploy_keys/store';
import deployKeysPanel from '~/deploy_keys/components/keys_panel.vue';
describe('Deploy keys panel', () => {
const data = getJSONFixture('deploy_keys/keys.json');
let vm;
let wrapper;
beforeEach(done => {
const DeployKeysPanelComponent = Vue.extend(deployKeysPanel);
const findTableRowHeader = () => wrapper.find('.table-row-header');
const mountComponent = props => {
const store = new DeployKeysStore();
store.keys = data;
vm = new DeployKeysPanelComponent({
wrapper = mount(deployKeysPanel, {
propsData: {
title: 'test',
keys: data.enabled_keys,
showHelpBox: true,
store,
endpoint: 'https://test.host/dummy/endpoint',
...props,
},
}).$mount();
});
};
setTimeout(done);
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('renders list of keys', () => {
expect(vm.$el.querySelectorAll('.deploy-key').length).toBe(vm.keys.length);
mountComponent();
expect(wrapper.findAll('.deploy-key').length).toBe(wrapper.vm.keys.length);
});
it('renders table header', () => {
const tableHeader = vm.$el.querySelector('.table-row-header');
mountComponent();
const tableHeader = findTableRowHeader();
expect(tableHeader).toExist();
expect(tableHeader.textContent).toContain('Deploy key');
expect(tableHeader.textContent).toContain('Project usage');
expect(tableHeader.textContent).toContain('Created');
expect(tableHeader.text()).toContain('Deploy key');
expect(tableHeader.text()).toContain('Project usage');
expect(tableHeader.text()).toContain('Created');
});
it('renders help box if keys are empty', done => {
vm.keys = [];
Vue.nextTick(() => {
expect(vm.$el.querySelector('.settings-message')).toBeDefined();
it('renders help box if keys are empty', () => {
mountComponent({ keys: [] });
expect(vm.$el.querySelector('.settings-message').textContent.trim()).toBe(
'No deploy keys found. Create one with the form above.',
);
expect(wrapper.find('.settings-message').exists()).toBe(true);
done();
});
expect(
wrapper
.find('.settings-message')
.text()
.trim(),
).toBe('No deploy keys found. Create one with the form above.');
});
it('renders no table header if keys are empty', done => {
vm.keys = [];
Vue.nextTick(() => {
expect(vm.$el.querySelector('.table-row-header')).not.toExist();
done();
});
it('renders no table header if keys are empty', () => {
mountComponent({ keys: [] });
expect(findTableRowHeader().exists()).toBe(false);
});
});
import Vue from 'vue';
import eventHub from '~/deploy_keys/eventhub';
import actionBtn from '~/deploy_keys/components/action_btn.vue';
describe('Deploy keys action btn', () => {
const data = getJSONFixture('deploy_keys/keys.json');
const deployKey = data.enabled_keys[0];
let vm;
beforeEach(done => {
const ActionBtnComponent = Vue.extend({
components: {
actionBtn,
},
data() {
return {
deployKey,
};
},
template: `
<action-btn
:deploy-key="deployKey"
type="enable">
Enable
</action-btn>`,
});
vm = new ActionBtnComponent().$mount();
Vue.nextTick()
.then(done)
.catch(done.fail);
});
it('renders the default slot', () => {
expect(vm.$el.textContent.trim()).toBe('Enable');
});
it('sends eventHub event with btn type', done => {
spyOn(eventHub, '$emit');
vm.$el.click();
Vue.nextTick(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('enable.key', deployKey, jasmine.anything());
done();
});
});
it('shows loading spinner after click', done => {
vm.$el.click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.fa')).toBeDefined();
done();
});
});
it('disables button after click', done => {
vm.$el.click();
Vue.nextTick(() => {
expect(vm.$el.classList.contains('disabled')).toBeTruthy();
expect(vm.$el.getAttribute('disabled')).toBe('disabled');
done();
});
});
});
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import eventHub from '~/deploy_keys/eventhub';
import deployKeysApp from '~/deploy_keys/components/app.vue';
describe('Deploy keys app component', () => {
const data = getJSONFixture('deploy_keys/keys.json');
let vm;
let mock;
beforeEach(done => {
// set up axios mock before component
mock = new MockAdapter(axios);
mock.onGet(`${TEST_HOST}/dummy/`).replyOnce(200, data);
const Component = Vue.extend(deployKeysApp);
vm = new Component({
propsData: {
endpoint: `${TEST_HOST}/dummy`,
projectId: '8',
},
}).$mount();
setTimeout(done);
});
afterEach(() => {
mock.restore();
});
it('renders loading icon', done => {
vm.store.keys = {};
vm.isLoading = false;
Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(0);
expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
done();
});
});
it('renders keys panels', () => {
expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(3);
});
it('renders the titles with keys count', () => {
const textContent = selector => {
const element = vm.$el.querySelector(`${selector}`);
expect(element).not.toBeNull();
return element.textContent.trim();
};
expect(textContent('.js-deployKeys-tab-enabled_keys')).toContain('Enabled deploy keys');
expect(textContent('.js-deployKeys-tab-available_project_keys')).toContain(
'Privately accessible deploy keys',
);
expect(textContent('.js-deployKeys-tab-public_keys')).toContain(
'Publicly accessible deploy keys',
);
expect(textContent('.js-deployKeys-tab-enabled_keys .badge')).toBe(
`${vm.store.keys.enabled_keys.length}`,
);
expect(textContent('.js-deployKeys-tab-available_project_keys .badge')).toBe(
`${vm.store.keys.available_project_keys.length}`,
);
expect(textContent('.js-deployKeys-tab-public_keys .badge')).toBe(
`${vm.store.keys.public_keys.length}`,
);
});
it('does not render key panels when keys object is empty', done => {
vm.store.keys = {};
Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('.deploy-keys .nav-links li').length).toBe(0);
done();
});
});
it('re-fetches deploy keys when enabling a key', done => {
const key = data.public_keys[0];
spyOn(vm.service, 'getKeys');
spyOn(vm.service, 'enableKey').and.callFake(() => Promise.resolve());
eventHub.$emit('enable.key', key);
Vue.nextTick(() => {
expect(vm.service.enableKey).toHaveBeenCalledWith(key.id);
expect(vm.service.getKeys).toHaveBeenCalled();
done();
});
});
it('re-fetches deploy keys when disabling a key', done => {
const key = data.public_keys[0];
spyOn(window, 'confirm').and.returnValue(true);
spyOn(vm.service, 'getKeys');
spyOn(vm.service, 'disableKey').and.callFake(() => Promise.resolve());
eventHub.$emit('disable.key', key);
Vue.nextTick(() => {
expect(vm.service.disableKey).toHaveBeenCalledWith(key.id);
expect(vm.service.getKeys).toHaveBeenCalled();
done();
});
});
it('calls disableKey when removing a key', done => {
const key = data.public_keys[0];
spyOn(window, 'confirm').and.returnValue(true);
spyOn(vm.service, 'getKeys');
spyOn(vm.service, 'disableKey').and.callFake(() => Promise.resolve());
eventHub.$emit('remove.key', key);
Vue.nextTick(() => {
expect(vm.service.disableKey).toHaveBeenCalledWith(key.id);
expect(vm.service.getKeys).toHaveBeenCalled();
done();
});
});
it('hasKeys returns true when there are keys', () => {
expect(vm.hasKeys).toEqual(3);
});
it('resets disable button loading state', done => {
spyOn(window, 'confirm').and.returnValue(false);
const btn = vm.$el.querySelector('.btn-warning');
btn.click();
Vue.nextTick(() => {
expect(btn.querySelector('.btn-warning')).not.toExist();
done();
});
});
});
import Vue from 'vue';
import DeployKeysStore from '~/deploy_keys/store';
import key from '~/deploy_keys/components/key.vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Deploy keys key', () => {
let vm;
const KeyComponent = Vue.extend(key);
const data = getJSONFixture('deploy_keys/keys.json');
const createComponent = deployKey => {
const store = new DeployKeysStore();
store.keys = data;
vm = new KeyComponent({
propsData: {
deployKey,
store,
endpoint: 'https://test.host/dummy/endpoint',
},
}).$mount();
};
describe('enabled key', () => {
const deployKey = data.enabled_keys[0];
beforeEach(done => {
createComponent(deployKey);
setTimeout(done);
});
it('renders the keys title', () => {
expect(vm.$el.querySelector('.title').textContent.trim()).toContain('My title');
});
it('renders human friendly formatted created date', () => {
expect(vm.$el.querySelector('.key-created-at').textContent.trim()).toBe(
`${getTimeago().format(deployKey.created_at)}`,
);
});
it('shows pencil button for editing', () => {
expect(vm.$el.querySelector('.btn .ic-pencil')).toExist();
});
it('shows disable button when the project is not deletable', () => {
expect(vm.$el.querySelector('.btn .ic-cancel')).toExist();
});
it('shows remove button when the project is deletable', done => {
vm.deployKey.destroyed_when_orphaned = true;
vm.deployKey.almost_orphaned = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.btn .ic-remove')).toExist();
done();
});
});
});
describe('deploy key labels', () => {
it('shows write access title when key has write access', done => {
vm.deployKey.deploy_keys_projects[0].can_push = true;
Vue.nextTick(() => {
expect(
vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'),
).toBe('Write access allowed');
done();
});
});
it('does not show write access title when key has write access', done => {
vm.deployKey.deploy_keys_projects[0].can_push = false;
Vue.nextTick(() => {
expect(
vm.$el.querySelector('.deploy-project-label').getAttribute('data-original-title'),
).toBe('Read access only');
done();
});
});
it('shows expandable button if more than two projects', () => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain('others');
expect(labels[1].getAttribute('data-original-title')).toContain('Expand');
});
it('expands all project labels after click', done => {
const { length } = vm.deployKey.deploy_keys_projects;
vm.$el.querySelectorAll('.deploy-project-label')[1].click();
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(length);
expect(labels[1].textContent).not.toContain(`+${length} others`);
expect(labels[1].getAttribute('data-original-title')).not.toContain('Expand');
done();
});
});
it('shows two projects', done => {
vm.deployKey.deploy_keys_projects = [...vm.deployKey.deploy_keys_projects].slice(0, 2);
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain(
vm.deployKey.deploy_keys_projects[1].project.full_name,
);
done();
});
});
});
describe('public keys', () => {
const deployKey = data.public_keys[0];
beforeEach(done => {
createComponent(deployKey);
setTimeout(done);
});
it('renders deploy keys without any enabled projects', done => {
vm.deployKey.deploy_keys_projects = [];
Vue.nextTick(() => {
expect(vm.$el.querySelector('.deploy-project-list').textContent.trim()).toBe('None');
done();
});
});
it('shows enable button', () => {
expect(vm.$el.querySelectorAll('.btn')[0].textContent.trim()).toBe('Enable');
});
it('shows pencil button for editing', () => {
expect(vm.$el.querySelector('.btn .ic-pencil')).toExist();
});
it('shows disable button when key is enabled', done => {
vm.store.keys.enabled_keys.push(deployKey);
Vue.nextTick(() => {
expect(vm.$el.querySelector('.btn .ic-cancel')).toExist();
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